aboutsummaryrefslogtreecommitdiffstats
path: root/Plugins/DbSqliteCipher
diff options
context:
space:
mode:
authorLibravatarUnit 193 <unit193@unit193.net>2023-04-30 18:30:36 -0400
committerLibravatarUnit 193 <unit193@unit193.net>2023-04-30 18:30:36 -0400
commit3565aad630864ecdbe53fdaa501ea708555b3c7c (patch)
treec743e4ad0bad39ebdb2f514c7cc52d34a257ebbe /Plugins/DbSqliteCipher
parent1fdc150116cad39aae5c5da407c3312b47a59e3a (diff)
New upstream version 3.4.4+dfsg.upstream/3.4.4+dfsg
Diffstat (limited to 'Plugins/DbSqliteCipher')
-rw-r--r--Plugins/DbSqliteCipher/DbSqliteCipher.pro29
-rw-r--r--Plugins/DbSqliteCipher/DbSqliteCipher_de.qmbin23 -> 0 bytes
-rw-r--r--Plugins/DbSqliteCipher/DbSqliteCipher_de.ts58
-rw-r--r--Plugins/DbSqliteCipher/DbSqliteCipher_es.qmbin23 -> 0 bytes
-rw-r--r--Plugins/DbSqliteCipher/DbSqliteCipher_es.ts58
-rw-r--r--Plugins/DbSqliteCipher/DbSqliteCipher_fr.qmbin23 -> 0 bytes
-rw-r--r--Plugins/DbSqliteCipher/DbSqliteCipher_fr.ts58
-rw-r--r--Plugins/DbSqliteCipher/DbSqliteCipher_it.qmbin23 -> 0 bytes
-rw-r--r--Plugins/DbSqliteCipher/DbSqliteCipher_it.ts58
-rw-r--r--Plugins/DbSqliteCipher/DbSqliteCipher_pl.qmbin1812 -> 0 bytes
-rw-r--r--Plugins/DbSqliteCipher/DbSqliteCipher_pl.ts58
-rw-r--r--Plugins/DbSqliteCipher/DbSqliteCipher_pt_BR.qmbin23 -> 0 bytes
-rw-r--r--Plugins/DbSqliteCipher/DbSqliteCipher_pt_BR.ts58
-rw-r--r--Plugins/DbSqliteCipher/DbSqliteCipher_ro_RO.qmbin30 -> 0 bytes
-rw-r--r--Plugins/DbSqliteCipher/DbSqliteCipher_ro_RO.ts58
-rw-r--r--Plugins/DbSqliteCipher/DbSqliteCipher_ru.qmbin34 -> 0 bytes
-rw-r--r--Plugins/DbSqliteCipher/DbSqliteCipher_ru.ts58
-rw-r--r--Plugins/DbSqliteCipher/DbSqliteCipher_sk.qmbin27 -> 0 bytes
-rw-r--r--Plugins/DbSqliteCipher/DbSqliteCipher_sk.ts58
-rw-r--r--Plugins/DbSqliteCipher/DbSqliteCipher_zh_CN.qm1
-rw-r--r--Plugins/DbSqliteCipher/DbSqliteCipher_zh_CN.ts58
-rw-r--r--Plugins/DbSqliteCipher/dbsqlitecipher.cpp5
-rw-r--r--Plugins/DbSqliteCipher/dbsqlitecipher.json2
-rw-r--r--Plugins/DbSqliteCipher/dbsqlitecipherinstance.cpp12
-rw-r--r--Plugins/DbSqliteCipher/dbsqlitecipherinstance.h3
-rw-r--r--Plugins/DbSqliteCipher/sqlcipher.c44879
-rw-r--r--Plugins/DbSqliteCipher/sqlcipher.h762
-rw-r--r--Plugins/DbSqliteCipher/translations/DbSqliteCipher.ts34
-rw-r--r--Plugins/DbSqliteCipher/translations/DbSqliteCipher_af_ZA.ts36
-rw-r--r--Plugins/DbSqliteCipher/translations/DbSqliteCipher_ar_SA.ts36
-rw-r--r--Plugins/DbSqliteCipher/translations/DbSqliteCipher_ca_ES.ts36
-rw-r--r--Plugins/DbSqliteCipher/translations/DbSqliteCipher_cs_CZ.ts36
-rw-r--r--Plugins/DbSqliteCipher/translations/DbSqliteCipher_da_DK.ts36
-rw-r--r--Plugins/DbSqliteCipher/translations/DbSqliteCipher_de_DE.ts36
-rw-r--r--Plugins/DbSqliteCipher/translations/DbSqliteCipher_el_GR.ts36
-rw-r--r--Plugins/DbSqliteCipher/translations/DbSqliteCipher_en_US.ts36
-rw-r--r--Plugins/DbSqliteCipher/translations/DbSqliteCipher_es_ES.ts36
-rw-r--r--Plugins/DbSqliteCipher/translations/DbSqliteCipher_fa_IR.ts36
-rw-r--r--Plugins/DbSqliteCipher/translations/DbSqliteCipher_fi_FI.ts36
-rw-r--r--Plugins/DbSqliteCipher/translations/DbSqliteCipher_fr_FR.ts36
-rw-r--r--Plugins/DbSqliteCipher/translations/DbSqliteCipher_he_IL.ts36
-rw-r--r--Plugins/DbSqliteCipher/translations/DbSqliteCipher_hu_HU.ts36
-rw-r--r--Plugins/DbSqliteCipher/translations/DbSqliteCipher_it_IT.ts36
-rw-r--r--Plugins/DbSqliteCipher/translations/DbSqliteCipher_ja_JP.ts36
-rw-r--r--Plugins/DbSqliteCipher/translations/DbSqliteCipher_kaa.ts36
-rw-r--r--Plugins/DbSqliteCipher/translations/DbSqliteCipher_ko_KR.ts36
-rw-r--r--Plugins/DbSqliteCipher/translations/DbSqliteCipher_nl_NL.ts36
-rw-r--r--Plugins/DbSqliteCipher/translations/DbSqliteCipher_no_NO.ts36
-rw-r--r--Plugins/DbSqliteCipher/translations/DbSqliteCipher_pl_PL.ts36
-rw-r--r--Plugins/DbSqliteCipher/translations/DbSqliteCipher_pt_BR.ts36
-rw-r--r--Plugins/DbSqliteCipher/translations/DbSqliteCipher_pt_PT.ts36
-rw-r--r--Plugins/DbSqliteCipher/translations/DbSqliteCipher_ro_RO.ts36
-rw-r--r--Plugins/DbSqliteCipher/translations/DbSqliteCipher_ru_RU.ts36
-rw-r--r--Plugins/DbSqliteCipher/translations/DbSqliteCipher_sk_SK.ts36
-rw-r--r--Plugins/DbSqliteCipher/translations/DbSqliteCipher_sr_SP.ts36
-rw-r--r--Plugins/DbSqliteCipher/translations/DbSqliteCipher_sv_SE.ts36
-rw-r--r--Plugins/DbSqliteCipher/translations/DbSqliteCipher_tr_TR.ts36
-rw-r--r--Plugins/DbSqliteCipher/translations/DbSqliteCipher_uk_UA.ts36
-rw-r--r--Plugins/DbSqliteCipher/translations/DbSqliteCipher_vi_VN.ts36
-rw-r--r--Plugins/DbSqliteCipher/translations/DbSqliteCipher_zh_CN.ts36
-rw-r--r--Plugins/DbSqliteCipher/translations/DbSqliteCipher_zh_TW.ts36
-rw-r--r--Plugins/DbSqliteCipher/update_sqlite_version.tcl2
62 files changed, 29603 insertions, 17894 deletions
diff --git a/Plugins/DbSqliteCipher/DbSqliteCipher.pro b/Plugins/DbSqliteCipher/DbSqliteCipher.pro
index 1c9b041..33cd7c6 100644
--- a/Plugins/DbSqliteCipher/DbSqliteCipher.pro
+++ b/Plugins/DbSqliteCipher/DbSqliteCipher.pro
@@ -26,8 +26,15 @@ HEADERS += dbsqlitecipher.h \
sqlcipher.h
mac: {
- INCLUDEPATH += /usr/local/opt/openssl/include
- LIBS += -L/usr/local/opt/openssl/lib
+ exists( /opt/local/include/openssl-3/openssl/crypto.h ) {
+ message( "Configuring OpenSSL from MacPorts" )
+ INCLUDEPATH += /opt/local/include/openssl-3
+ LIBS += -L/opt/local/lib/openssl-3
+ } else {
+ message( "Configuring OpenSSL from HomeBrew" )
+ INCLUDEPATH += /usr/local/opt/openssl/include
+ LIBS += -L/usr/local/opt/openssl/lib
+ }
}
!macx: {
LIBS += -L$${PWD}/../deps/lib/$${PLATFORM}/
@@ -81,15 +88,11 @@ QMAKE_CFLAGS_WARN_ON = -Wall -Wno-unused-parameter -Wno-sign-compare -Wno-unused
DISTFILES += \
openssl_lic.txt
-TRANSLATIONS += DbSqliteCipher_ro_RO.ts \
- DbSqliteCipher_de.ts \
- \
- DbSqliteCipher_it.ts\
- DbSqliteCipher_zh_CN.ts\
- DbSqliteCipher_sk.ts\
- DbSqliteCipher_ru.ts\
- DbSqliteCipher_pt_BR.ts\
- DbSqliteCipher_fr.ts\
- DbSqliteCipher_es.ts\
- DbSqliteCipher_pl.ts
+
+
+
+
+
+
+
diff --git a/Plugins/DbSqliteCipher/DbSqliteCipher_de.qm b/Plugins/DbSqliteCipher/DbSqliteCipher_de.qm
deleted file mode 100644
index 9dad8df..0000000
--- a/Plugins/DbSqliteCipher/DbSqliteCipher_de.qm
+++ /dev/null
Binary files differ
diff --git a/Plugins/DbSqliteCipher/DbSqliteCipher_de.ts b/Plugins/DbSqliteCipher/DbSqliteCipher_de.ts
deleted file mode 100644
index 932d4f7..0000000
--- a/Plugins/DbSqliteCipher/DbSqliteCipher_de.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE TS>
-<TS version="2.1" language="de_DE">
-<context>
- <name>DbSqliteCipher</name>
- <message>
- <location filename="dbsqlitecipher.cpp" line="43"/>
- <source>Password (key)</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="44"/>
- <source>Leave empty to create or connect to decrypted database.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="45"/>
- <source>Encryption password</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="50"/>
- <source>Cipher</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="51"/>
- <source>Must be the same as the one used when creating the database. %1 is the default one.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="59"/>
- <source>KDF iterations</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="63"/>
- <location filename="dbsqlitecipher.cpp" line="72"/>
- <source>Must be the same as the one used when creating the database. %1 is the default.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="68"/>
- <source>Cipher page size</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="77"/>
- <source>1.1 compatibility</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="79"/>
- <source>Enabling this option disables HMAC checks introduced in SQLCipher 2.0, thus making the connection compatible with SQLCipher 1.1.x.</source>
- <translation type="unfinished"></translation>
- </message>
-</context>
-</TS>
diff --git a/Plugins/DbSqliteCipher/DbSqliteCipher_es.qm b/Plugins/DbSqliteCipher/DbSqliteCipher_es.qm
deleted file mode 100644
index 9dad8df..0000000
--- a/Plugins/DbSqliteCipher/DbSqliteCipher_es.qm
+++ /dev/null
Binary files differ
diff --git a/Plugins/DbSqliteCipher/DbSqliteCipher_es.ts b/Plugins/DbSqliteCipher/DbSqliteCipher_es.ts
deleted file mode 100644
index c9c3654..0000000
--- a/Plugins/DbSqliteCipher/DbSqliteCipher_es.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE TS>
-<TS version="2.1" language="es_ES">
-<context>
- <name>DbSqliteCipher</name>
- <message>
- <location filename="dbsqlitecipher.cpp" line="43"/>
- <source>Password (key)</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="44"/>
- <source>Leave empty to create or connect to decrypted database.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="45"/>
- <source>Encryption password</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="50"/>
- <source>Cipher</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="51"/>
- <source>Must be the same as the one used when creating the database. %1 is the default one.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="59"/>
- <source>KDF iterations</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="63"/>
- <location filename="dbsqlitecipher.cpp" line="72"/>
- <source>Must be the same as the one used when creating the database. %1 is the default.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="68"/>
- <source>Cipher page size</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="77"/>
- <source>1.1 compatibility</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="79"/>
- <source>Enabling this option disables HMAC checks introduced in SQLCipher 2.0, thus making the connection compatible with SQLCipher 1.1.x.</source>
- <translation type="unfinished"></translation>
- </message>
-</context>
-</TS>
diff --git a/Plugins/DbSqliteCipher/DbSqliteCipher_fr.qm b/Plugins/DbSqliteCipher/DbSqliteCipher_fr.qm
deleted file mode 100644
index c02994c..0000000
--- a/Plugins/DbSqliteCipher/DbSqliteCipher_fr.qm
+++ /dev/null
Binary files differ
diff --git a/Plugins/DbSqliteCipher/DbSqliteCipher_fr.ts b/Plugins/DbSqliteCipher/DbSqliteCipher_fr.ts
deleted file mode 100644
index cc3f2da..0000000
--- a/Plugins/DbSqliteCipher/DbSqliteCipher_fr.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE TS>
-<TS version="2.1" language="fr_FR">
-<context>
- <name>DbSqliteCipher</name>
- <message>
- <location filename="dbsqlitecipher.cpp" line="43"/>
- <source>Password (key)</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="44"/>
- <source>Leave empty to create or connect to decrypted database.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="45"/>
- <source>Encryption password</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="50"/>
- <source>Cipher</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="51"/>
- <source>Must be the same as the one used when creating the database. %1 is the default one.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="59"/>
- <source>KDF iterations</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="63"/>
- <location filename="dbsqlitecipher.cpp" line="72"/>
- <source>Must be the same as the one used when creating the database. %1 is the default.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="68"/>
- <source>Cipher page size</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="77"/>
- <source>1.1 compatibility</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="79"/>
- <source>Enabling this option disables HMAC checks introduced in SQLCipher 2.0, thus making the connection compatible with SQLCipher 1.1.x.</source>
- <translation type="unfinished"></translation>
- </message>
-</context>
-</TS>
diff --git a/Plugins/DbSqliteCipher/DbSqliteCipher_it.qm b/Plugins/DbSqliteCipher/DbSqliteCipher_it.qm
deleted file mode 100644
index 9dad8df..0000000
--- a/Plugins/DbSqliteCipher/DbSqliteCipher_it.qm
+++ /dev/null
Binary files differ
diff --git a/Plugins/DbSqliteCipher/DbSqliteCipher_it.ts b/Plugins/DbSqliteCipher/DbSqliteCipher_it.ts
deleted file mode 100644
index 435c396..0000000
--- a/Plugins/DbSqliteCipher/DbSqliteCipher_it.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE TS>
-<TS version="2.1" language="it_IT">
-<context>
- <name>DbSqliteCipher</name>
- <message>
- <location filename="dbsqlitecipher.cpp" line="43"/>
- <source>Password (key)</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="44"/>
- <source>Leave empty to create or connect to decrypted database.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="45"/>
- <source>Encryption password</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="50"/>
- <source>Cipher</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="51"/>
- <source>Must be the same as the one used when creating the database. %1 is the default one.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="59"/>
- <source>KDF iterations</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="63"/>
- <location filename="dbsqlitecipher.cpp" line="72"/>
- <source>Must be the same as the one used when creating the database. %1 is the default.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="68"/>
- <source>Cipher page size</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="77"/>
- <source>1.1 compatibility</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="79"/>
- <source>Enabling this option disables HMAC checks introduced in SQLCipher 2.0, thus making the connection compatible with SQLCipher 1.1.x.</source>
- <translation type="unfinished"></translation>
- </message>
-</context>
-</TS>
diff --git a/Plugins/DbSqliteCipher/DbSqliteCipher_pl.qm b/Plugins/DbSqliteCipher/DbSqliteCipher_pl.qm
deleted file mode 100644
index 38239cc..0000000
--- a/Plugins/DbSqliteCipher/DbSqliteCipher_pl.qm
+++ /dev/null
Binary files differ
diff --git a/Plugins/DbSqliteCipher/DbSqliteCipher_pl.ts b/Plugins/DbSqliteCipher/DbSqliteCipher_pl.ts
deleted file mode 100644
index 3e25fcf..0000000
--- a/Plugins/DbSqliteCipher/DbSqliteCipher_pl.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE TS>
-<TS version="2.1" language="pl_PL">
-<context>
- <name>DbSqliteCipher</name>
- <message>
- <location filename="dbsqlitecipher.cpp" line="43"/>
- <source>Password (key)</source>
- <translation>Hasło (klucz)</translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="44"/>
- <source>Leave empty to create or connect to decrypted database.</source>
- <translation>Pozostaw puste, aby stworzyć lub połączyć się z niezaszyfrowaną bazą.</translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="45"/>
- <source>Encryption password</source>
- <translation>Hasło szyfrowania</translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="50"/>
- <source>Cipher</source>
- <translation>Szyfr (cihper)</translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="51"/>
- <source>Must be the same as the one used when creating the database. %1 is the default one.</source>
- <translation>Musi być taki sam jak ten użyty podczas tworzenia bazy. Domyślny to %1.</translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="59"/>
- <source>KDF iterations</source>
- <translation>Powtórzenia KDF</translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="63"/>
- <location filename="dbsqlitecipher.cpp" line="72"/>
- <source>Must be the same as the one used when creating the database. %1 is the default.</source>
- <translation>Muszą być takie same jak te użyte podczas tworzenia bazy. Domyślnie to %1.</translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="68"/>
- <source>Cipher page size</source>
- <translation>Rozmiar strony szyfru</translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="77"/>
- <source>1.1 compatibility</source>
- <translation>kompatybilność z 1.1</translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="79"/>
- <source>Enabling this option disables HMAC checks introduced in SQLCipher 2.0, thus making the connection compatible with SQLCipher 1.1.x.</source>
- <translation>Włączenie tej opcji wyłącza weryfikacje HMAC wprowadzone w SQLCipher 2.0, stwarzając w ten sposób połączenie kompatybilne z SQLCipher 1.1.x.</translation>
- </message>
-</context>
-</TS>
diff --git a/Plugins/DbSqliteCipher/DbSqliteCipher_pt_BR.qm b/Plugins/DbSqliteCipher/DbSqliteCipher_pt_BR.qm
deleted file mode 100644
index c02994c..0000000
--- a/Plugins/DbSqliteCipher/DbSqliteCipher_pt_BR.qm
+++ /dev/null
Binary files differ
diff --git a/Plugins/DbSqliteCipher/DbSqliteCipher_pt_BR.ts b/Plugins/DbSqliteCipher/DbSqliteCipher_pt_BR.ts
deleted file mode 100644
index e656317..0000000
--- a/Plugins/DbSqliteCipher/DbSqliteCipher_pt_BR.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE TS>
-<TS version="2.1" language="pt_BR">
-<context>
- <name>DbSqliteCipher</name>
- <message>
- <location filename="dbsqlitecipher.cpp" line="43"/>
- <source>Password (key)</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="44"/>
- <source>Leave empty to create or connect to decrypted database.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="45"/>
- <source>Encryption password</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="50"/>
- <source>Cipher</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="51"/>
- <source>Must be the same as the one used when creating the database. %1 is the default one.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="59"/>
- <source>KDF iterations</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="63"/>
- <location filename="dbsqlitecipher.cpp" line="72"/>
- <source>Must be the same as the one used when creating the database. %1 is the default.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="68"/>
- <source>Cipher page size</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="77"/>
- <source>1.1 compatibility</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="79"/>
- <source>Enabling this option disables HMAC checks introduced in SQLCipher 2.0, thus making the connection compatible with SQLCipher 1.1.x.</source>
- <translation type="unfinished"></translation>
- </message>
-</context>
-</TS>
diff --git a/Plugins/DbSqliteCipher/DbSqliteCipher_ro_RO.qm b/Plugins/DbSqliteCipher/DbSqliteCipher_ro_RO.qm
deleted file mode 100644
index 2856eb9..0000000
--- a/Plugins/DbSqliteCipher/DbSqliteCipher_ro_RO.qm
+++ /dev/null
Binary files differ
diff --git a/Plugins/DbSqliteCipher/DbSqliteCipher_ro_RO.ts b/Plugins/DbSqliteCipher/DbSqliteCipher_ro_RO.ts
deleted file mode 100644
index 2dc7d47..0000000
--- a/Plugins/DbSqliteCipher/DbSqliteCipher_ro_RO.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE TS>
-<TS version="2.1" language="ro_RO">
-<context>
- <name>DbSqliteCipher</name>
- <message>
- <location filename="dbsqlitecipher.cpp" line="43"/>
- <source>Password (key)</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="44"/>
- <source>Leave empty to create or connect to decrypted database.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="45"/>
- <source>Encryption password</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="50"/>
- <source>Cipher</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="51"/>
- <source>Must be the same as the one used when creating the database. %1 is the default one.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="59"/>
- <source>KDF iterations</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="63"/>
- <location filename="dbsqlitecipher.cpp" line="72"/>
- <source>Must be the same as the one used when creating the database. %1 is the default.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="68"/>
- <source>Cipher page size</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="77"/>
- <source>1.1 compatibility</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="79"/>
- <source>Enabling this option disables HMAC checks introduced in SQLCipher 2.0, thus making the connection compatible with SQLCipher 1.1.x.</source>
- <translation type="unfinished"></translation>
- </message>
-</context>
-</TS>
diff --git a/Plugins/DbSqliteCipher/DbSqliteCipher_ru.qm b/Plugins/DbSqliteCipher/DbSqliteCipher_ru.qm
deleted file mode 100644
index 7431612..0000000
--- a/Plugins/DbSqliteCipher/DbSqliteCipher_ru.qm
+++ /dev/null
Binary files differ
diff --git a/Plugins/DbSqliteCipher/DbSqliteCipher_ru.ts b/Plugins/DbSqliteCipher/DbSqliteCipher_ru.ts
deleted file mode 100644
index ca11a83..0000000
--- a/Plugins/DbSqliteCipher/DbSqliteCipher_ru.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE TS>
-<TS version="2.0" language="ru_RU">
-<context>
- <name>DbSqliteCipher</name>
- <message>
- <location filename="dbsqlitecipher.cpp" line="43"/>
- <source>Password (key)</source>
- <translation>Пароль (ключ)</translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="44"/>
- <source>Leave empty to create or connect to decrypted database.</source>
- <translation>Оставьте пустым для создания или подключения к расшифрованной базе данных</translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="45"/>
- <source>Encryption password</source>
- <translation>Пароль для шифрования</translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="50"/>
- <source>Cipher</source>
- <translation>Шифр</translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="51"/>
- <source>Must be the same as the one used when creating the database. %1 is the default one.</source>
- <translation>Должен совпадать с использованным при создании базы данных. По умолчанию используется %1.</translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="59"/>
- <source>KDF iterations</source>
- <translation>Количество итераций KDF</translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="63"/>
- <location filename="dbsqlitecipher.cpp" line="72"/>
- <source>Must be the same as the one used when creating the database. %1 is the default.</source>
- <translation>Должно совпадать с использованным при создании базы данных. По умолчанию используется %1.</translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="68"/>
- <source>Cipher page size</source>
- <translation>Размер страницы шифра</translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="77"/>
- <source>1.1 compatibility</source>
- <translation>Совместимость с 1.1</translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="79"/>
- <source>Enabling this option disables HMAC checks introduced in SQLCipher 2.0, thus making the connection compatible with SQLCipher 1.1.x.</source>
- <translation>Включение этой опции отключает проверки HMAC, реализованные в SQLCipher 2.0, обеспечивая совместимость подключения с SQLCipher 1.1.x.</translation>
- </message>
-</context>
-</TS>
diff --git a/Plugins/DbSqliteCipher/DbSqliteCipher_sk.qm b/Plugins/DbSqliteCipher/DbSqliteCipher_sk.qm
deleted file mode 100644
index 1776294..0000000
--- a/Plugins/DbSqliteCipher/DbSqliteCipher_sk.qm
+++ /dev/null
Binary files differ
diff --git a/Plugins/DbSqliteCipher/DbSqliteCipher_sk.ts b/Plugins/DbSqliteCipher/DbSqliteCipher_sk.ts
deleted file mode 100644
index 4f3d58b..0000000
--- a/Plugins/DbSqliteCipher/DbSqliteCipher_sk.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE TS>
-<TS version="2.1" language="sk_SK">
-<context>
- <name>DbSqliteCipher</name>
- <message>
- <location filename="dbsqlitecipher.cpp" line="43"/>
- <source>Password (key)</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="44"/>
- <source>Leave empty to create or connect to decrypted database.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="45"/>
- <source>Encryption password</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="50"/>
- <source>Cipher</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="51"/>
- <source>Must be the same as the one used when creating the database. %1 is the default one.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="59"/>
- <source>KDF iterations</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="63"/>
- <location filename="dbsqlitecipher.cpp" line="72"/>
- <source>Must be the same as the one used when creating the database. %1 is the default.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="68"/>
- <source>Cipher page size</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="77"/>
- <source>1.1 compatibility</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="79"/>
- <source>Enabling this option disables HMAC checks introduced in SQLCipher 2.0, thus making the connection compatible with SQLCipher 1.1.x.</source>
- <translation type="unfinished"></translation>
- </message>
-</context>
-</TS>
diff --git a/Plugins/DbSqliteCipher/DbSqliteCipher_zh_CN.qm b/Plugins/DbSqliteCipher/DbSqliteCipher_zh_CN.qm
deleted file mode 100644
index be651ee..0000000
--- a/Plugins/DbSqliteCipher/DbSqliteCipher_zh_CN.qm
+++ /dev/null
@@ -1 +0,0 @@
-<d!` \ No newline at end of file
diff --git a/Plugins/DbSqliteCipher/DbSqliteCipher_zh_CN.ts b/Plugins/DbSqliteCipher/DbSqliteCipher_zh_CN.ts
deleted file mode 100644
index 39bc943..0000000
--- a/Plugins/DbSqliteCipher/DbSqliteCipher_zh_CN.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE TS>
-<TS version="2.1" language="zh_CN">
-<context>
- <name>DbSqliteCipher</name>
- <message>
- <location filename="dbsqlitecipher.cpp" line="43"/>
- <source>Password (key)</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="44"/>
- <source>Leave empty to create or connect to decrypted database.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="45"/>
- <source>Encryption password</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="50"/>
- <source>Cipher</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="51"/>
- <source>Must be the same as the one used when creating the database. %1 is the default one.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="59"/>
- <source>KDF iterations</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="63"/>
- <location filename="dbsqlitecipher.cpp" line="72"/>
- <source>Must be the same as the one used when creating the database. %1 is the default.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="68"/>
- <source>Cipher page size</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="77"/>
- <source>1.1 compatibility</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="dbsqlitecipher.cpp" line="79"/>
- <source>Enabling this option disables HMAC checks introduced in SQLCipher 2.0, thus making the connection compatible with SQLCipher 1.1.x.</source>
- <translation type="unfinished"></translation>
- </message>
-</context>
-</TS>
diff --git a/Plugins/DbSqliteCipher/dbsqlitecipher.cpp b/Plugins/DbSqliteCipher/dbsqlitecipher.cpp
index fba9640..b2357d6 100644
--- a/Plugins/DbSqliteCipher/dbsqlitecipher.cpp
+++ b/Plugins/DbSqliteCipher/dbsqlitecipher.cpp
@@ -45,7 +45,7 @@ QList<DbPluginOption> DbSqliteCipher::getOptionsList() const
bool DbSqliteCipher::init()
{
- Q_INIT_RESOURCE(dbsqlitecipher);
+ SQLS_INIT_RESOURCE(dbsqlitecipher);
if (!SQLITESTUDIO->getExtraLicenseManager()->addLicense(LICENSE_TITLE, ":/license/sqlcipher.txt"))
{
@@ -66,7 +66,8 @@ bool DbSqliteCipher::init()
void DbSqliteCipher::deinit()
{
SQLITESTUDIO->getExtraLicenseManager()->removeLicense(LICENSE_TITLE);
- Q_CLEANUP_RESOURCE(dbsqlitecipher);
+ SQLITESTUDIO->getExtraLicenseManager()->removeLicense(OPENSSL_TITLE);
+ SQLS_CLEANUP_RESOURCE(dbsqlitecipher);
}
Db *DbSqliteCipher::newInstance(const QString &name, const QString &path, const QHash<QString, QVariant> &options)
diff --git a/Plugins/DbSqliteCipher/dbsqlitecipher.json b/Plugins/DbSqliteCipher/dbsqlitecipher.json
index 08a69bd..7ba1851 100644
--- a/Plugins/DbSqliteCipher/dbsqlitecipher.json
+++ b/Plugins/DbSqliteCipher/dbsqlitecipher.json
@@ -3,6 +3,6 @@
"title": "SQLCipher",
"description": "Provides support for databases encrypted with SQLCipher (https://www.zetetic.net/sqlcipher/). See 'About' dialog for SQLCipher license.",
"minAppVersion": 30300,
- "version": 10200,
+ "version": 10201,
"author": "SalSoft"
}
diff --git a/Plugins/DbSqliteCipher/dbsqlitecipherinstance.cpp b/Plugins/DbSqliteCipher/dbsqlitecipherinstance.cpp
index 1f838f6..512d5dc 100644
--- a/Plugins/DbSqliteCipher/dbsqlitecipherinstance.cpp
+++ b/Plugins/DbSqliteCipher/dbsqlitecipherinstance.cpp
@@ -7,6 +7,16 @@ DbSqliteCipherInstance::DbSqliteCipherInstance(const QString& name, const QStrin
{
}
+Db* DbSqliteCipherInstance::clone() const
+{
+ return new DbSqliteCipherInstance(name, path, connOptions);
+}
+
+QString DbSqliteCipherInstance::getTypeClassName() const
+{
+ return "DbSqliteCipherInstance";
+}
+
void DbSqliteCipherInstance::initAfterOpen()
{
SqlQueryPtr res;
@@ -14,7 +24,7 @@ void DbSqliteCipherInstance::initAfterOpen()
QString key = connOptions[DbSqliteCipher::PASSWORD_OPT].toString();
if (!key.isEmpty())
{
- res = exec(QString("PRAGMA key = '%1';").arg(key), Flag::NO_LOCK);
+ res = exec(QString("PRAGMA key = '%1';").arg(escapeString(key)), Flag::NO_LOCK);
if (res->isError())
qWarning() << "Error while defining SQLCipher key:" << res->getErrorText();
}
diff --git a/Plugins/DbSqliteCipher/dbsqlitecipherinstance.h b/Plugins/DbSqliteCipher/dbsqlitecipherinstance.h
index 68b2710..21eb1dd 100644
--- a/Plugins/DbSqliteCipher/dbsqlitecipherinstance.h
+++ b/Plugins/DbSqliteCipher/dbsqlitecipherinstance.h
@@ -22,6 +22,9 @@ class DbSqliteCipherInstance : public AbstractDb3<SqlCipher>
public:
DbSqliteCipherInstance(const QString& name, const QString& path, const QHash<QString, QVariant>& connOptions);
+ Db* clone() const;
+ QString getTypeClassName() const;
+
protected:
void initAfterOpen();
QString getAttachSql(Db* otherDb, const QString& generatedAttachName);
diff --git a/Plugins/DbSqliteCipher/sqlcipher.c b/Plugins/DbSqliteCipher/sqlcipher.c
index 4e39565..0a86228 100644
--- a/Plugins/DbSqliteCipher/sqlcipher.c
+++ b/Plugins/DbSqliteCipher/sqlcipher.c
@@ -1,6 +1,6 @@
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
-** version 3.34.1. By combining all the individual C code files into this
+** version 3.39.4. 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
@@ -23,776 +23,6 @@
# define SQLITE_PRIVATE static
#endif
#define SQLITE_UDL_CAPABLE_PARSER 1
-/************** Begin file ctime.c *******************************************/
-/*
-** 2010 February 23
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-**
-** This file implements routines used to report what compile-time options
-** SQLite was built with.
-*/
-
-#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS /* IMP: R-16824-07538 */
-
-/*
-** Include the configuration header output by 'configure' if we're using the
-** autoconf-based build
-*/
-#if defined(_HAVE_SQLITE_CONFIG_H) && !defined(SQLITECONFIG_H)
-#include "config.h"
-#define SQLITECONFIG_H 1
-#endif
-
-/* These macros are provided to "stringify" the value of the define
-** for those options in which the value is meaningful. */
-#define CTIMEOPT_VAL_(opt) #opt
-#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
-
-/* Like CTIMEOPT_VAL, but especially for SQLITE_DEFAULT_LOOKASIDE. This
-** option requires a separate macro because legal values contain a single
-** comma. e.g. (-DSQLITE_DEFAULT_LOOKASIDE="100,100") */
-#define CTIMEOPT_VAL2_(opt1,opt2) #opt1 "," #opt2
-#define CTIMEOPT_VAL2(opt) CTIMEOPT_VAL2_(opt)
-
-/*
-** An array of names of all compile-time options. This array should
-** be sorted A-Z.
-**
-** This array looks large, but in a typical installation actually uses
-** only a handful of compile-time options, so most times this array is usually
-** rather short and uses little memory space.
-*/
-static const char * const sqlcipher_sqlite3azCompileOpt[] = {
-
-/*
-** BEGIN CODE GENERATED BY tool/mkctime.tcl
-*/
-#if SQLITE_32BIT_ROWID
- "32BIT_ROWID",
-#endif
-#if SQLITE_4_BYTE_ALIGNED_MALLOC
- "4_BYTE_ALIGNED_MALLOC",
-#endif
-#if SQLITE_64BIT_STATS
- "64BIT_STATS",
-#endif
-#if SQLITE_ALLOW_COVERING_INDEX_SCAN
- "ALLOW_COVERING_INDEX_SCAN",
-#endif
-#if SQLITE_ALLOW_URI_AUTHORITY
- "ALLOW_URI_AUTHORITY",
-#endif
-#ifdef SQLITE_BITMASK_TYPE
- "BITMASK_TYPE=" CTIMEOPT_VAL(SQLITE_BITMASK_TYPE),
-#endif
-#if SQLITE_BUG_COMPATIBLE_20160819
- "BUG_COMPATIBLE_20160819",
-#endif
-#if SQLITE_CASE_SENSITIVE_LIKE
- "CASE_SENSITIVE_LIKE",
-#endif
-#if SQLITE_CHECK_PAGES
- "CHECK_PAGES",
-#endif
-#if defined(__clang__) && defined(__clang_major__)
- "COMPILER=clang-" CTIMEOPT_VAL(__clang_major__) "."
- CTIMEOPT_VAL(__clang_minor__) "."
- CTIMEOPT_VAL(__clang_patchlevel__),
-#elif defined(_MSC_VER)
- "COMPILER=msvc-" CTIMEOPT_VAL(_MSC_VER),
-#elif defined(__GNUC__) && defined(__VERSION__)
- "COMPILER=gcc-" __VERSION__,
-#endif
-#if SQLITE_COVERAGE_TEST
- "COVERAGE_TEST",
-#endif
-#if SQLITE_DEBUG
- "DEBUG",
-#endif
-#if SQLITE_DEFAULT_AUTOMATIC_INDEX
- "DEFAULT_AUTOMATIC_INDEX",
-#endif
-#if SQLITE_DEFAULT_AUTOVACUUM
- "DEFAULT_AUTOVACUUM",
-#endif
-#ifdef SQLITE_DEFAULT_CACHE_SIZE
- "DEFAULT_CACHE_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_CACHE_SIZE),
-#endif
-#if SQLITE_DEFAULT_CKPTFULLFSYNC
- "DEFAULT_CKPTFULLFSYNC",
-#endif
-#ifdef SQLITE_DEFAULT_FILE_FORMAT
- "DEFAULT_FILE_FORMAT=" CTIMEOPT_VAL(SQLITE_DEFAULT_FILE_FORMAT),
-#endif
-#ifdef SQLITE_DEFAULT_FILE_PERMISSIONS
- "DEFAULT_FILE_PERMISSIONS=" CTIMEOPT_VAL(SQLITE_DEFAULT_FILE_PERMISSIONS),
-#endif
-#if SQLITE_DEFAULT_FOREIGN_KEYS
- "DEFAULT_FOREIGN_KEYS",
-#endif
-#ifdef SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT
- "DEFAULT_JOURNAL_SIZE_LIMIT=" CTIMEOPT_VAL(SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT),
-#endif
-#ifdef SQLITE_DEFAULT_LOCKING_MODE
- "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE),
-#endif
-#ifdef SQLITE_DEFAULT_LOOKASIDE
- "DEFAULT_LOOKASIDE=" CTIMEOPT_VAL2(SQLITE_DEFAULT_LOOKASIDE),
-#endif
-#if SQLITE_DEFAULT_MEMSTATUS
- "DEFAULT_MEMSTATUS",
-#endif
-#ifdef SQLITE_DEFAULT_MMAP_SIZE
- "DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE),
-#endif
-#ifdef SQLITE_DEFAULT_PAGE_SIZE
- "DEFAULT_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_PAGE_SIZE),
-#endif
-#ifdef SQLITE_DEFAULT_PCACHE_INITSZ
- "DEFAULT_PCACHE_INITSZ=" CTIMEOPT_VAL(SQLITE_DEFAULT_PCACHE_INITSZ),
-#endif
-#ifdef SQLITE_DEFAULT_PROXYDIR_PERMISSIONS
- "DEFAULT_PROXYDIR_PERMISSIONS=" CTIMEOPT_VAL(SQLITE_DEFAULT_PROXYDIR_PERMISSIONS),
-#endif
-#if SQLITE_DEFAULT_RECURSIVE_TRIGGERS
- "DEFAULT_RECURSIVE_TRIGGERS",
-#endif
-#ifdef SQLITE_DEFAULT_ROWEST
- "DEFAULT_ROWEST=" CTIMEOPT_VAL(SQLITE_DEFAULT_ROWEST),
-#endif
-#ifdef SQLITE_DEFAULT_SECTOR_SIZE
- "DEFAULT_SECTOR_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_SECTOR_SIZE),
-#endif
-#ifdef SQLITE_DEFAULT_SYNCHRONOUS
- "DEFAULT_SYNCHRONOUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_SYNCHRONOUS),
-#endif
-#ifdef SQLITE_DEFAULT_WAL_AUTOCHECKPOINT
- "DEFAULT_WAL_AUTOCHECKPOINT=" CTIMEOPT_VAL(SQLITE_DEFAULT_WAL_AUTOCHECKPOINT),
-#endif
-#ifdef SQLITE_DEFAULT_WAL_SYNCHRONOUS
- "DEFAULT_WAL_SYNCHRONOUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_WAL_SYNCHRONOUS),
-#endif
-#ifdef SQLITE_DEFAULT_WORKER_THREADS
- "DEFAULT_WORKER_THREADS=" CTIMEOPT_VAL(SQLITE_DEFAULT_WORKER_THREADS),
-#endif
-#if SQLITE_DIRECT_OVERFLOW_READ
- "DIRECT_OVERFLOW_READ",
-#endif
-#if SQLITE_DISABLE_DIRSYNC
- "DISABLE_DIRSYNC",
-#endif
-#if SQLITE_DISABLE_FTS3_UNICODE
- "DISABLE_FTS3_UNICODE",
-#endif
-#if SQLITE_DISABLE_FTS4_DEFERRED
- "DISABLE_FTS4_DEFERRED",
-#endif
-#if SQLITE_DISABLE_INTRINSIC
- "DISABLE_INTRINSIC",
-#endif
-#if SQLITE_DISABLE_LFS
- "DISABLE_LFS",
-#endif
-#if SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
- "DISABLE_PAGECACHE_OVERFLOW_STATS",
-#endif
-#if SQLITE_DISABLE_SKIPAHEAD_DISTINCT
- "DISABLE_SKIPAHEAD_DISTINCT",
-#endif
-#ifdef SQLITE_ENABLE_8_3_NAMES
- "ENABLE_8_3_NAMES=" CTIMEOPT_VAL(SQLITE_ENABLE_8_3_NAMES),
-#endif
-#if SQLITE_ENABLE_API_ARMOR
- "ENABLE_API_ARMOR",
-#endif
-#if SQLITE_ENABLE_ATOMIC_WRITE
- "ENABLE_ATOMIC_WRITE",
-#endif
-#if SQLITE_ENABLE_BATCH_ATOMIC_WRITE
- "ENABLE_BATCH_ATOMIC_WRITE",
-#endif
-#if SQLITE_ENABLE_BYTECODE_VTAB
- "ENABLE_BYTECODE_VTAB",
-#endif
-#if SQLITE_ENABLE_CEROD
- "ENABLE_CEROD=" CTIMEOPT_VAL(SQLITE_ENABLE_CEROD),
-#endif
-#if SQLITE_ENABLE_COLUMN_METADATA
- "ENABLE_COLUMN_METADATA",
-#endif
-#if SQLITE_ENABLE_COLUMN_USED_MASK
- "ENABLE_COLUMN_USED_MASK",
-#endif
-#if SQLITE_ENABLE_COSTMULT
- "ENABLE_COSTMULT",
-#endif
-#if SQLITE_ENABLE_CURSOR_HINTS
- "ENABLE_CURSOR_HINTS",
-#endif
-#if SQLITE_ENABLE_DBSTAT_VTAB
- "ENABLE_DBSTAT_VTAB",
-#endif
-#if SQLITE_ENABLE_EXPENSIVE_ASSERT
- "ENABLE_EXPENSIVE_ASSERT",
-#endif
-#if SQLITE_ENABLE_FTS1
- "ENABLE_FTS1",
-#endif
-#if SQLITE_ENABLE_FTS2
- "ENABLE_FTS2",
-#endif
-#if SQLITE_ENABLE_FTS3
- "ENABLE_FTS3",
-#endif
-#if SQLITE_ENABLE_FTS3_PARENTHESIS
- "ENABLE_FTS3_PARENTHESIS",
-#endif
-#if SQLITE_ENABLE_FTS3_TOKENIZER
- "ENABLE_FTS3_TOKENIZER",
-#endif
-#if SQLITE_ENABLE_FTS4
- "ENABLE_FTS4",
-#endif
-#if SQLITE_ENABLE_FTS5
- "ENABLE_FTS5",
-#endif
-#if SQLITE_ENABLE_GEOPOLY
- "ENABLE_GEOPOLY",
-#endif
-#if SQLITE_ENABLE_HIDDEN_COLUMNS
- "ENABLE_HIDDEN_COLUMNS",
-#endif
-#if SQLITE_ENABLE_ICU
- "ENABLE_ICU",
-#endif
-#if SQLITE_ENABLE_IOTRACE
- "ENABLE_IOTRACE",
-#endif
-#if SQLITE_ENABLE_JSON1
- "ENABLE_JSON1",
-#endif
-#if SQLITE_ENABLE_LOAD_EXTENSION
- "ENABLE_LOAD_EXTENSION",
-#endif
-#ifdef SQLITE_ENABLE_LOCKING_STYLE
- "ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE),
-#endif
-#if SQLITE_ENABLE_MEMORY_MANAGEMENT
- "ENABLE_MEMORY_MANAGEMENT",
-#endif
-#if SQLITE_ENABLE_MEMSYS3
- "ENABLE_MEMSYS3",
-#endif
-#if SQLITE_ENABLE_MEMSYS5
- "ENABLE_MEMSYS5",
-#endif
-#if SQLITE_ENABLE_MULTIPLEX
- "ENABLE_MULTIPLEX",
-#endif
-#if SQLITE_ENABLE_NORMALIZE
- "ENABLE_NORMALIZE",
-#endif
-#if SQLITE_ENABLE_NULL_TRIM
- "ENABLE_NULL_TRIM",
-#endif
-#if SQLITE_ENABLE_OVERSIZE_CELL_CHECK
- "ENABLE_OVERSIZE_CELL_CHECK",
-#endif
-#if SQLITE_ENABLE_PREUPDATE_HOOK
- "ENABLE_PREUPDATE_HOOK",
-#endif
-#if SQLITE_ENABLE_QPSG
- "ENABLE_QPSG",
-#endif
-#if SQLITE_ENABLE_RBU
- "ENABLE_RBU",
-#endif
-#if SQLITE_ENABLE_RTREE
- "ENABLE_RTREE",
-#endif
-#if SQLITE_ENABLE_SELECTTRACE
- "ENABLE_SELECTTRACE",
-#endif
-#if SQLITE_ENABLE_SESSION
- "ENABLE_SESSION",
-#endif
-#if SQLITE_ENABLE_SNAPSHOT
- "ENABLE_SNAPSHOT",
-#endif
-#if SQLITE_ENABLE_SORTER_REFERENCES
- "ENABLE_SORTER_REFERENCES",
-#endif
-#if SQLITE_ENABLE_SQLLOG
- "ENABLE_SQLLOG",
-#endif
-#if defined(SQLITE_ENABLE_STAT4)
- "ENABLE_STAT4",
-#endif
-#if SQLITE_ENABLE_STMTVTAB
- "ENABLE_STMTVTAB",
-#endif
-#if SQLITE_ENABLE_STMT_SCANSTATUS
- "ENABLE_STMT_SCANSTATUS",
-#endif
-#if SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
- "ENABLE_UNKNOWN_SQL_FUNCTION",
-#endif
-#if SQLITE_ENABLE_UNLOCK_NOTIFY
- "ENABLE_UNLOCK_NOTIFY",
-#endif
-#if SQLITE_ENABLE_UPDATE_DELETE_LIMIT
- "ENABLE_UPDATE_DELETE_LIMIT",
-#endif
-#if SQLITE_ENABLE_URI_00_ERROR
- "ENABLE_URI_00_ERROR",
-#endif
-#if SQLITE_ENABLE_VFSTRACE
- "ENABLE_VFSTRACE",
-#endif
-#if SQLITE_ENABLE_WHERETRACE
- "ENABLE_WHERETRACE",
-#endif
-#if SQLITE_ENABLE_ZIPVFS
- "ENABLE_ZIPVFS",
-#endif
-#if SQLITE_EXPLAIN_ESTIMATED_ROWS
- "EXPLAIN_ESTIMATED_ROWS",
-#endif
-#if SQLITE_EXTRA_IFNULLROW
- "EXTRA_IFNULLROW",
-#endif
-#ifdef SQLITE_EXTRA_INIT
- "EXTRA_INIT=" CTIMEOPT_VAL(SQLITE_EXTRA_INIT),
-#endif
-#ifdef SQLITE_EXTRA_SHUTDOWN
- "EXTRA_SHUTDOWN=" CTIMEOPT_VAL(SQLITE_EXTRA_SHUTDOWN),
-#endif
-#ifdef SQLITE_FTS3_MAX_EXPR_DEPTH
- "FTS3_MAX_EXPR_DEPTH=" CTIMEOPT_VAL(SQLITE_FTS3_MAX_EXPR_DEPTH),
-#endif
-#if SQLITE_FTS5_ENABLE_TEST_MI
- "FTS5_ENABLE_TEST_MI",
-#endif
-#if SQLITE_FTS5_NO_WITHOUT_ROWID
- "FTS5_NO_WITHOUT_ROWID",
-#endif
-/* BEGIN SQLCIPHER */
-#if SQLITE_HAS_CODEC
- "HAS_CODEC",
-#endif
-/* END SQLCIPHER */
-#if HAVE_ISNAN || SQLITE_HAVE_ISNAN
- "HAVE_ISNAN",
-#endif
-#if SQLITE_HOMEGROWN_RECURSIVE_MUTEX
- "HOMEGROWN_RECURSIVE_MUTEX",
-#endif
-#if SQLITE_IGNORE_AFP_LOCK_ERRORS
- "IGNORE_AFP_LOCK_ERRORS",
-#endif
-#if SQLITE_IGNORE_FLOCK_LOCK_ERRORS
- "IGNORE_FLOCK_LOCK_ERRORS",
-#endif
-#if SQLITE_INLINE_MEMCPY
- "INLINE_MEMCPY",
-#endif
-#if SQLITE_INT64_TYPE
- "INT64_TYPE",
-#endif
-#ifdef SQLITE_INTEGRITY_CHECK_ERROR_MAX
- "INTEGRITY_CHECK_ERROR_MAX=" CTIMEOPT_VAL(SQLITE_INTEGRITY_CHECK_ERROR_MAX),
-#endif
-#if SQLITE_LIKE_DOESNT_MATCH_BLOBS
- "LIKE_DOESNT_MATCH_BLOBS",
-#endif
-#if SQLITE_LOCK_TRACE
- "LOCK_TRACE",
-#endif
-#if SQLITE_LOG_CACHE_SPILL
- "LOG_CACHE_SPILL",
-#endif
-#ifdef SQLITE_MALLOC_SOFT_LIMIT
- "MALLOC_SOFT_LIMIT=" CTIMEOPT_VAL(SQLITE_MALLOC_SOFT_LIMIT),
-#endif
-#ifdef SQLITE_MAX_ATTACHED
- "MAX_ATTACHED=" CTIMEOPT_VAL(SQLITE_MAX_ATTACHED),
-#endif
-#ifdef SQLITE_MAX_COLUMN
- "MAX_COLUMN=" CTIMEOPT_VAL(SQLITE_MAX_COLUMN),
-#endif
-#ifdef SQLITE_MAX_COMPOUND_SELECT
- "MAX_COMPOUND_SELECT=" CTIMEOPT_VAL(SQLITE_MAX_COMPOUND_SELECT),
-#endif
-#ifdef SQLITE_MAX_DEFAULT_PAGE_SIZE
- "MAX_DEFAULT_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_DEFAULT_PAGE_SIZE),
-#endif
-#ifdef SQLITE_MAX_EXPR_DEPTH
- "MAX_EXPR_DEPTH=" CTIMEOPT_VAL(SQLITE_MAX_EXPR_DEPTH),
-#endif
-#ifdef SQLITE_MAX_FUNCTION_ARG
- "MAX_FUNCTION_ARG=" CTIMEOPT_VAL(SQLITE_MAX_FUNCTION_ARG),
-#endif
-#ifdef SQLITE_MAX_LENGTH
- "MAX_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_LENGTH),
-#endif
-#ifdef SQLITE_MAX_LIKE_PATTERN_LENGTH
- "MAX_LIKE_PATTERN_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_LIKE_PATTERN_LENGTH),
-#endif
-#ifdef SQLITE_MAX_MEMORY
- "MAX_MEMORY=" CTIMEOPT_VAL(SQLITE_MAX_MEMORY),
-#endif
-#ifdef SQLITE_MAX_MMAP_SIZE
- "MAX_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_MMAP_SIZE),
-#endif
-#ifdef SQLITE_MAX_MMAP_SIZE_
- "MAX_MMAP_SIZE_=" CTIMEOPT_VAL(SQLITE_MAX_MMAP_SIZE_),
-#endif
-#ifdef SQLITE_MAX_PAGE_COUNT
- "MAX_PAGE_COUNT=" CTIMEOPT_VAL(SQLITE_MAX_PAGE_COUNT),
-#endif
-#ifdef SQLITE_MAX_PAGE_SIZE
- "MAX_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_PAGE_SIZE),
-#endif
-#ifdef SQLITE_MAX_SCHEMA_RETRY
- "MAX_SCHEMA_RETRY=" CTIMEOPT_VAL(SQLITE_MAX_SCHEMA_RETRY),
-#endif
-#ifdef SQLITE_MAX_SQL_LENGTH
- "MAX_SQL_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_SQL_LENGTH),
-#endif
-#ifdef SQLITE_MAX_TRIGGER_DEPTH
- "MAX_TRIGGER_DEPTH=" CTIMEOPT_VAL(SQLITE_MAX_TRIGGER_DEPTH),
-#endif
-#ifdef SQLITE_MAX_VARIABLE_NUMBER
- "MAX_VARIABLE_NUMBER=" CTIMEOPT_VAL(SQLITE_MAX_VARIABLE_NUMBER),
-#endif
-#ifdef SQLITE_MAX_VDBE_OP
- "MAX_VDBE_OP=" CTIMEOPT_VAL(SQLITE_MAX_VDBE_OP),
-#endif
-#ifdef SQLITE_MAX_WORKER_THREADS
- "MAX_WORKER_THREADS=" CTIMEOPT_VAL(SQLITE_MAX_WORKER_THREADS),
-#endif
-#if SQLITE_MEMDEBUG
- "MEMDEBUG",
-#endif
-#if SQLITE_MIXED_ENDIAN_64BIT_FLOAT
- "MIXED_ENDIAN_64BIT_FLOAT",
-#endif
-#if SQLITE_MMAP_READWRITE
- "MMAP_READWRITE",
-#endif
-#if SQLITE_MUTEX_NOOP
- "MUTEX_NOOP",
-#endif
-#if SQLITE_MUTEX_NREF
- "MUTEX_NREF",
-#endif
-#if SQLITE_MUTEX_OMIT
- "MUTEX_OMIT",
-#endif
-#if SQLITE_MUTEX_PTHREADS
- "MUTEX_PTHREADS",
-#endif
-#if SQLITE_MUTEX_W32
- "MUTEX_W32",
-#endif
-#if SQLITE_NEED_ERR_NAME
- "NEED_ERR_NAME",
-#endif
-#if SQLITE_NOINLINE
- "NOINLINE",
-#endif
-#if SQLITE_NO_SYNC
- "NO_SYNC",
-#endif
-#if SQLITE_OMIT_ALTERTABLE
- "OMIT_ALTERTABLE",
-#endif
-#if SQLITE_OMIT_ANALYZE
- "OMIT_ANALYZE",
-#endif
-#if SQLITE_OMIT_ATTACH
- "OMIT_ATTACH",
-#endif
-#if SQLITE_OMIT_AUTHORIZATION
- "OMIT_AUTHORIZATION",
-#endif
-#if SQLITE_OMIT_AUTOINCREMENT
- "OMIT_AUTOINCREMENT",
-#endif
-#if SQLITE_OMIT_AUTOINIT
- "OMIT_AUTOINIT",
-#endif
-#if SQLITE_OMIT_AUTOMATIC_INDEX
- "OMIT_AUTOMATIC_INDEX",
-#endif
-#if SQLITE_OMIT_AUTORESET
- "OMIT_AUTORESET",
-#endif
-#if SQLITE_OMIT_AUTOVACUUM
- "OMIT_AUTOVACUUM",
-#endif
-#if SQLITE_OMIT_BETWEEN_OPTIMIZATION
- "OMIT_BETWEEN_OPTIMIZATION",
-#endif
-#if SQLITE_OMIT_BLOB_LITERAL
- "OMIT_BLOB_LITERAL",
-#endif
-#if SQLITE_OMIT_CAST
- "OMIT_CAST",
-#endif
-#if SQLITE_OMIT_CHECK
- "OMIT_CHECK",
-#endif
-#if SQLITE_OMIT_COMPLETE
- "OMIT_COMPLETE",
-#endif
-#if SQLITE_OMIT_COMPOUND_SELECT
- "OMIT_COMPOUND_SELECT",
-#endif
-#if SQLITE_OMIT_CONFLICT_CLAUSE
- "OMIT_CONFLICT_CLAUSE",
-#endif
-#if SQLITE_OMIT_CTE
- "OMIT_CTE",
-#endif
-#if SQLITE_OMIT_DATETIME_FUNCS
- "OMIT_DATETIME_FUNCS",
-#endif
-#if SQLITE_OMIT_DECLTYPE
- "OMIT_DECLTYPE",
-#endif
-#if SQLITE_OMIT_DEPRECATED
- "OMIT_DEPRECATED",
-#endif
-#if SQLITE_OMIT_DISKIO
- "OMIT_DISKIO",
-#endif
-#if SQLITE_OMIT_EXPLAIN
- "OMIT_EXPLAIN",
-#endif
-#if SQLITE_OMIT_FLAG_PRAGMAS
- "OMIT_FLAG_PRAGMAS",
-#endif
-#if SQLITE_OMIT_FLOATING_POINT
- "OMIT_FLOATING_POINT",
-#endif
-#if SQLITE_OMIT_FOREIGN_KEY
- "OMIT_FOREIGN_KEY",
-#endif
-#if SQLITE_OMIT_GET_TABLE
- "OMIT_GET_TABLE",
-#endif
-#if SQLITE_OMIT_HEX_INTEGER
- "OMIT_HEX_INTEGER",
-#endif
-#if SQLITE_OMIT_INCRBLOB
- "OMIT_INCRBLOB",
-#endif
-#if SQLITE_OMIT_INTEGRITY_CHECK
- "OMIT_INTEGRITY_CHECK",
-#endif
-#if SQLITE_OMIT_LIKE_OPTIMIZATION
- "OMIT_LIKE_OPTIMIZATION",
-#endif
-#if SQLITE_OMIT_LOAD_EXTENSION
- "OMIT_LOAD_EXTENSION",
-#endif
-#if SQLITE_OMIT_LOCALTIME
- "OMIT_LOCALTIME",
-#endif
-#if SQLITE_OMIT_LOOKASIDE
- "OMIT_LOOKASIDE",
-#endif
-#if SQLITE_OMIT_MEMORYDB
- "OMIT_MEMORYDB",
-#endif
-#if SQLITE_OMIT_OR_OPTIMIZATION
- "OMIT_OR_OPTIMIZATION",
-#endif
-#if SQLITE_OMIT_PAGER_PRAGMAS
- "OMIT_PAGER_PRAGMAS",
-#endif
-#if SQLITE_OMIT_PARSER_TRACE
- "OMIT_PARSER_TRACE",
-#endif
-#if SQLITE_OMIT_POPEN
- "OMIT_POPEN",
-#endif
-#if SQLITE_OMIT_PRAGMA
- "OMIT_PRAGMA",
-#endif
-#if SQLITE_OMIT_PROGRESS_CALLBACK
- "OMIT_PROGRESS_CALLBACK",
-#endif
-#if SQLITE_OMIT_QUICKBALANCE
- "OMIT_QUICKBALANCE",
-#endif
-#if SQLITE_OMIT_REINDEX
- "OMIT_REINDEX",
-#endif
-#if SQLITE_OMIT_SCHEMA_PRAGMAS
- "OMIT_SCHEMA_PRAGMAS",
-#endif
-#if SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
- "OMIT_SCHEMA_VERSION_PRAGMAS",
-#endif
-#if SQLITE_OMIT_SHARED_CACHE
- "OMIT_SHARED_CACHE",
-#endif
-#if SQLITE_OMIT_SHUTDOWN_DIRECTORIES
- "OMIT_SHUTDOWN_DIRECTORIES",
-#endif
-#if SQLITE_OMIT_SUBQUERY
- "OMIT_SUBQUERY",
-#endif
-#if SQLITE_OMIT_TCL_VARIABLE
- "OMIT_TCL_VARIABLE",
-#endif
-#if SQLITE_OMIT_TEMPDB
- "OMIT_TEMPDB",
-#endif
-#if SQLITE_OMIT_TEST_CONTROL
- "OMIT_TEST_CONTROL",
-#endif
-#if SQLITE_OMIT_TRACE
- "OMIT_TRACE",
-#endif
-#if SQLITE_OMIT_TRIGGER
- "OMIT_TRIGGER",
-#endif
-#if SQLITE_OMIT_TRUNCATE_OPTIMIZATION
- "OMIT_TRUNCATE_OPTIMIZATION",
-#endif
-#if SQLITE_OMIT_UTF16
- "OMIT_UTF16",
-#endif
-#if SQLITE_OMIT_VACUUM
- "OMIT_VACUUM",
-#endif
-#if SQLITE_OMIT_VIEW
- "OMIT_VIEW",
-#endif
-#if SQLITE_OMIT_VIRTUALTABLE
- "OMIT_VIRTUALTABLE",
-#endif
-#if SQLITE_OMIT_WAL
- "OMIT_WAL",
-#endif
-#if SQLITE_OMIT_WSD
- "OMIT_WSD",
-#endif
-#if SQLITE_OMIT_XFER_OPT
- "OMIT_XFER_OPT",
-#endif
-#if SQLITE_PCACHE_SEPARATE_HEADER
- "PCACHE_SEPARATE_HEADER",
-#endif
-#if SQLITE_PERFORMANCE_TRACE
- "PERFORMANCE_TRACE",
-#endif
-#if SQLITE_POWERSAFE_OVERWRITE
- "POWERSAFE_OVERWRITE",
-#endif
-#if SQLITE_PREFER_PROXY_LOCKING
- "PREFER_PROXY_LOCKING",
-#endif
-#if SQLITE_PROXY_DEBUG
- "PROXY_DEBUG",
-#endif
-#if SQLITE_REVERSE_UNORDERED_SELECTS
- "REVERSE_UNORDERED_SELECTS",
-#endif
-#if SQLITE_RTREE_INT_ONLY
- "RTREE_INT_ONLY",
-#endif
-#if SQLITE_SECURE_DELETE
- "SECURE_DELETE",
-#endif
-#if SQLITE_SMALL_STACK
- "SMALL_STACK",
-#endif
-#ifdef SQLITE_SORTER_PMASZ
- "SORTER_PMASZ=" CTIMEOPT_VAL(SQLITE_SORTER_PMASZ),
-#endif
-#if SQLITE_SOUNDEX
- "SOUNDEX",
-#endif
-#ifdef SQLITE_STAT4_SAMPLES
- "STAT4_SAMPLES=" CTIMEOPT_VAL(SQLITE_STAT4_SAMPLES),
-#endif
-#ifdef SQLITE_STMTJRNL_SPILL
- "STMTJRNL_SPILL=" CTIMEOPT_VAL(SQLITE_STMTJRNL_SPILL),
-#endif
-#if SQLITE_SUBSTR_COMPATIBILITY
- "SUBSTR_COMPATIBILITY",
-#endif
-#if SQLITE_SYSTEM_MALLOC
- "SYSTEM_MALLOC",
-#endif
-#if SQLITE_TCL
- "TCL",
-#endif
-#ifdef SQLITE_TEMP_STORE
- "TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE),
-#endif
-#if SQLITE_TEST
- "TEST",
-#endif
-#if defined(SQLITE_THREADSAFE)
- "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE),
-#elif defined(THREADSAFE)
- "THREADSAFE=" CTIMEOPT_VAL(THREADSAFE),
-#else
- "THREADSAFE=1",
-#endif
-#if SQLITE_UNLINK_AFTER_CLOSE
- "UNLINK_AFTER_CLOSE",
-#endif
-#if SQLITE_UNTESTABLE
- "UNTESTABLE",
-#endif
-#if SQLITE_USER_AUTHENTICATION
- "USER_AUTHENTICATION",
-#endif
-#if SQLITE_USE_ALLOCA
- "USE_ALLOCA",
-#endif
-#if SQLITE_USE_FCNTL_TRACE
- "USE_FCNTL_TRACE",
-#endif
-#if SQLITE_USE_URI
- "USE_URI",
-#endif
-#if SQLITE_VDBE_COVERAGE
- "VDBE_COVERAGE",
-#endif
-#if SQLITE_WIN32_MALLOC
- "WIN32_MALLOC",
-#endif
-#if SQLITE_ZERO_MALLOC
- "ZERO_MALLOC",
-#endif
-/*
-** END CODE GENERATED BY tool/mkctime.tcl
-*/
-};
-
-SQLITE_PRIVATE const char **sqlcipher_sqlite3CompileOptions(int *pnOpt){
- *pnOpt = sizeof(sqlcipher_sqlite3azCompileOpt) / sizeof(sqlcipher_sqlite3azCompileOpt[0]);
- return (const char**)sqlcipher_sqlite3azCompileOpt;
-}
-
-#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
-
-/************** End of ctime.c ***********************************************/
/************** Begin file sqliteInt.h ***************************************/
/*
** 2001 September 15
@@ -996,6 +226,18 @@ SQLITE_PRIVATE const char **sqlcipher_sqlite3CompileOptions(int *pnOpt){
# define MSVC_VERSION 0
#endif
+/*
+** Some C99 functions in "math.h" are only present for MSVC when its version
+** is associated with Visual Studio 2013 or higher.
+*/
+#ifndef SQLITE_HAVE_C99_MATH_FUNCS
+# if MSVC_VERSION==0 || MSVC_VERSION>=1800
+# define SQLITE_HAVE_C99_MATH_FUNCS (1)
+# else
+# define SQLITE_HAVE_C99_MATH_FUNCS (0)
+# endif
+#endif
+
/* Needed for various definitions... */
#if defined(__GNUC__) && !defined(_GNU_SOURCE)
# define _GNU_SOURCE
@@ -1046,6 +288,17 @@ SQLITE_PRIVATE const char **sqlcipher_sqlite3CompileOptions(int *pnOpt){
# define _USE_32BIT_TIME_T
#endif
+/* Optionally #include a user-defined header, whereby compilation options
+** may be set prior to where they take effect, but after platform setup.
+** If SQLITE_CUSTOM_INCLUDE=? is defined, its value names the #include
+** file.
+*/
+#ifdef SQLITE_CUSTOM_INCLUDE
+# define INC_STRINGIFY_(f) #f
+# define INC_STRINGIFY(f) INC_STRINGIFY_(f)
+# include INC_STRINGIFY(SQLITE_CUSTOM_INCLUDE)
+#endif
+
/* 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.
@@ -1097,7 +350,30 @@ extern "C" {
/*
-** Provide the ability to override linkage features of the interface.
+** Facilitate override of interface linkage and calling conventions.
+** Be aware that these macros may not be used within this particular
+** translation of the amalgamation and its associated header file.
+**
+** The SQLITE_EXTERN and SQLITE_API macros are used to instruct the
+** compiler that the target identifier should have external linkage.
+**
+** The SQLITE_CDECL macro is used to set the calling convention for
+** public functions that accept a variable number of arguments.
+**
+** The SQLITE_APICALL macro is used to set the calling convention for
+** public functions that accept a fixed number of arguments.
+**
+** The SQLITE_STDCALL macro is no longer used and is now deprecated.
+**
+** The SQLITE_CALLBACK macro is used to set the calling convention for
+** function pointers.
+**
+** The SQLITE_SYSAPI macro is used to set the calling convention for
+** functions provided by the operating system.
+**
+** Currently, the SQLITE_CDECL, SQLITE_APICALL, SQLITE_CALLBACK, and
+** SQLITE_SYSAPI macros are used only when building for environments
+** that require non-default calling conventions.
*/
#ifndef SQLITE_EXTERN
# define SQLITE_EXTERN extern
@@ -1177,9 +453,9 @@ extern "C" {
** [sqlcipher_sqlite3_libversion_number()], [sqlcipher_sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-#define SQLITE_VERSION "3.34.1"
-#define SQLITE_VERSION_NUMBER 3034001
-#define SQLITE_SOURCE_ID "2021-01-20 14:10:07 10e20c0b43500cfb9bbc0eaa061c57514f715d87238f4d835880cd846b9ealt1"
+#define SQLITE_VERSION "3.39.4"
+#define SQLITE_VERSION_NUMBER 3039004
+#define SQLITE_SOURCE_ID "2022-09-29 15:55:41 a29f9949895322123f7c38fbe94c649a9d6e6c9cd0c3b41c96d694552f26alt1"
/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -1591,12 +867,13 @@ SQLITE_API int sqlcipher_sqlite3_exec(
#define SQLITE_CONSTRAINT_VTAB (SQLITE_CONSTRAINT | (9<<8))
#define SQLITE_CONSTRAINT_ROWID (SQLITE_CONSTRAINT |(10<<8))
#define SQLITE_CONSTRAINT_PINNED (SQLITE_CONSTRAINT |(11<<8))
+#define SQLITE_CONSTRAINT_DATATYPE (SQLITE_CONSTRAINT |(12<<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))
#define SQLITE_AUTH_USER (SQLITE_AUTH | (1<<8))
#define SQLITE_OK_LOAD_PERMANENTLY (SQLITE_OK | (1<<8))
-#define SQLITE_OK_SYMLINK (SQLITE_OK | (2<<8))
+#define SQLITE_OK_SYMLINK (SQLITE_OK | (2<<8)) /* internal use only */
/*
** CAPI3REF: Flags For File Open Operations
@@ -1604,6 +881,19 @@ SQLITE_API int sqlcipher_sqlite3_exec(
** These bit values are intended for use in the
** 3rd parameter to the [sqlcipher_sqlite3_open_v2()] interface and
** in the 4th parameter to the [sqlcipher_sqlite3_vfs.xOpen] method.
+**
+** Only those flags marked as "Ok for sqlcipher_sqlite3_open_v2()" may be
+** used as the third argument to the [sqlcipher_sqlite3_open_v2()] interface.
+** The other flags have historically been ignored by sqlcipher_sqlite3_open_v2(),
+** though future versions of SQLite might change so that an error is
+** raised if any of the disallowed bits are passed into sqlcipher_sqlite3_open_v2().
+** Applications should not depend on the historical behavior.
+**
+** Note in particular that passing the SQLITE_OPEN_EXCLUSIVE flag into
+** [sqlcipher_sqlite3_open_v2()] does *not* cause the underlying database file
+** to be opened using O_EXCL. Passing SQLITE_OPEN_EXCLUSIVE into
+** [sqlcipher_sqlite3_open_v2()] has historically be a no-op and might become an
+** error in future versions of SQLite.
*/
#define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlcipher_sqlite3_open_v2() */
#define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlcipher_sqlite3_open_v2() */
@@ -1626,6 +916,7 @@ SQLITE_API int sqlcipher_sqlite3_exec(
#define SQLITE_OPEN_PRIVATECACHE 0x00040000 /* Ok for sqlcipher_sqlite3_open_v2() */
#define SQLITE_OPEN_WAL 0x00080000 /* VFS only */
#define SQLITE_OPEN_NOFOLLOW 0x01000000 /* Ok for sqlcipher_sqlite3_open_v2() */
+#define SQLITE_OPEN_EXRESCODE 0x02000000 /* Extended result codes */
/* Reserved: 0x00F00000 */
/* Legacy compatibility: */
@@ -2182,6 +1473,23 @@ struct sqlcipher_sqlite3_io_methods {
** file to the database file, but before the *-shm file is updated to
** record the fact that the pages have been checkpointed.
** </ul>
+**
+** <li>[[SQLITE_FCNTL_EXTERNAL_READER]]
+** The EXPERIMENTAL [SQLITE_FCNTL_EXTERNAL_READER] opcode is used to detect
+** whether or not there is a database client in another process with a wal-mode
+** transaction open on the database or not. It is only available on unix.The
+** (void*) argument passed with this file-control should be a pointer to a
+** value of type (int). The integer value is set to 1 if the database is a wal
+** mode database and there exists at least one client in another process that
+** currently has an SQL transaction open on the database. It is set to 0 if
+** the database is not a wal-mode db, or if there is no such connection in any
+** other process. This opcode cannot be used to detect transactions opened
+** by clients within the current process, only within other processes.
+** </ul>
+**
+** <li>[[SQLITE_FCNTL_CKSM_FILE]]
+** Used by the cksmvfs VFS module only.
+** </ul>
*/
#define SQLITE_FCNTL_LOCKSTATE 1
#define SQLITE_FCNTL_GET_LOCKPROXYFILE 2
@@ -2221,6 +1529,8 @@ struct sqlcipher_sqlite3_io_methods {
#define SQLITE_FCNTL_CKPT_DONE 37
#define SQLITE_FCNTL_RESERVE_BYTES 38
#define SQLITE_FCNTL_CKPT_START 39
+#define SQLITE_FCNTL_EXTERNAL_READER 40
+#define SQLITE_FCNTL_CKSM_FILE 41
/* deprecated names */
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
@@ -3169,7 +2479,13 @@ struct sqlcipher_sqlite3_mem_methods {
** The second parameter is a pointer to an integer into which
** is written 0 or 1 to indicate whether triggers are disabled or enabled
** following this call. The second parameter may be a NULL pointer, in
-** which case the trigger setting is not reported back. </dd>
+** which case the trigger setting is not reported back.
+**
+** <p>Originally this option disabled all triggers. ^(However, since
+** SQLite version 3.35.0, TEMP triggers are still allowed even if
+** this option is off. So, in other words, this option now only disables
+** triggers in the main database schema or in the schemas of ATTACH-ed
+** databases.)^ </dd>
**
** [[SQLITE_DBCONFIG_ENABLE_VIEW]]
** <dt>SQLITE_DBCONFIG_ENABLE_VIEW</dt>
@@ -3180,7 +2496,13 @@ struct sqlcipher_sqlite3_mem_methods {
** The second parameter is a pointer to an integer into which
** is written 0 or 1 to indicate whether views are disabled or enabled
** following this call. The second parameter may be a NULL pointer, in
-** which case the view setting is not reported back. </dd>
+** which case the view setting is not reported back.
+**
+** <p>Originally this option disabled all views. ^(However, since
+** SQLite version 3.35.0, TEMP views are still allowed even if
+** this option is off. So, in other words, this option now only disables
+** views in the main database schema or in the schemas of ATTACH-ed
+** databases.)^ </dd>
**
** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]]
** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt>
@@ -3487,11 +2809,14 @@ SQLITE_API void sqlcipher_sqlite3_set_last_insert_rowid(sqlcipher_sqlite3*,sqlci
** CAPI3REF: Count The Number Of Rows Modified
** METHOD: sqlcipher_sqlite3
**
-** ^This function returns the number of rows modified, inserted or
+** ^These functions return the number of rows modified, inserted or
** deleted by the most recently completed INSERT, UPDATE or DELETE
** statement on the database connection specified by the only parameter.
-** ^Executing any other type of SQL statement does not modify the value
-** returned by this function.
+** The two functions are identical except for the type of the return value
+** and that if the number of rows modified by the most recent INSERT, UPDATE
+** or DELETE is greater than the maximum value supported by type "int", then
+** the return value of sqlcipher_sqlite3_changes() is undefined. ^Executing any other
+** type of SQL statement does not modify the value returned by these functions.
**
** ^Only changes made directly by the INSERT, UPDATE or DELETE statement are
** considered - auxiliary changes caused by [CREATE TRIGGER | triggers],
@@ -3540,16 +2865,21 @@ SQLITE_API void sqlcipher_sqlite3_set_last_insert_rowid(sqlcipher_sqlite3*,sqlci
** </ul>
*/
SQLITE_API int sqlcipher_sqlite3_changes(sqlcipher_sqlite3*);
+SQLITE_API sqlcipher_sqlite3_int64 sqlcipher_sqlite3_changes64(sqlcipher_sqlite3*);
/*
** CAPI3REF: Total Number Of Rows Modified
** METHOD: sqlcipher_sqlite3
**
-** ^This function returns the total number of rows inserted, modified or
+** ^These functions return the total number of rows inserted, modified or
** deleted by all [INSERT], [UPDATE] or [DELETE] statements completed
** since the database connection was opened, including those executed as
-** part of trigger programs. ^Executing any other type of SQL statement
-** does not affect the value returned by sqlcipher_sqlite3_total_changes().
+** part of trigger programs. The two functions are identical except for the
+** type of the return value and that if the number of rows modified by the
+** connection exceeds the maximum value supported by type "int", then
+** the return value of sqlcipher_sqlite3_total_changes() is undefined. ^Executing
+** any other type of SQL statement does not affect the value returned by
+** sqlcipher_sqlite3_total_changes().
**
** ^Changes made as part of [foreign key actions] are included in the
** count, but those made as part of REPLACE constraint resolution are
@@ -3577,6 +2907,7 @@ SQLITE_API int sqlcipher_sqlite3_changes(sqlcipher_sqlite3*);
** </ul>
*/
SQLITE_API int sqlcipher_sqlite3_total_changes(sqlcipher_sqlite3*);
+SQLITE_API sqlcipher_sqlite3_int64 sqlcipher_sqlite3_total_changes64(sqlcipher_sqlite3*);
/*
** CAPI3REF: Interrupt A Long-Running Query
@@ -4406,6 +3737,14 @@ SQLITE_API void sqlcipher_sqlite3_progress_handler(sqlcipher_sqlite3*, int, int(
** the default shared cache setting provided by
** [sqlcipher_sqlite3_enable_shared_cache()].)^
**
+** [[OPEN_EXRESCODE]] ^(<dt>[SQLITE_OPEN_EXRESCODE]</dt>
+** <dd>The database connection comes up in "extended result code mode".
+** In other words, the database behaves has if
+** [sqlcipher_sqlite3_extended_result_codes(db,1)] where called on the database
+** connection as soon as the connection is created. In addition to setting
+** the extended result code mode, this flag also causes [sqlcipher_sqlite3_open_v2()]
+** to return an extended result code.</dd>
+**
** [[OPEN_NOFOLLOW]] ^(<dt>[SQLITE_OPEN_NOFOLLOW]</dt>
** <dd>The database filename is not allowed to be a symbolic link</dd>
** </dl>)^
@@ -4413,7 +3752,15 @@ SQLITE_API void sqlcipher_sqlite3_progress_handler(sqlcipher_sqlite3*, int, int(
** If the 3rd parameter to sqlcipher_sqlite3_open_v2() is not one of the
** required combinations shown above optionally combined with other
** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits]
-** then the behavior is undefined.
+** then the behavior is undefined. Historic versions of SQLite
+** have silently ignored surplus bits in the flags parameter to
+** sqlcipher_sqlite3_open_v2(), however that behavior might not be carried through
+** into future versions of SQLite and so applications should not rely
+** upon it. Note in particular that the SQLITE_OPEN_EXCLUSIVE flag is a no-op
+** for sqlcipher_sqlite3_open_v2(). The SQLITE_OPEN_EXCLUSIVE does *not* cause
+** the open to fail if the database already exists. The SQLITE_OPEN_EXCLUSIVE
+** flag is intended for use by the [sqlcipher_sqlite3_vfs|VFS interface] only, and not
+** by sqlcipher_sqlite3_open_v2().
**
** ^The fourth parameter to sqlcipher_sqlite3_open_v2() is the name of the
** [sqlcipher_sqlite3_vfs] object that defines the operating system interface that
@@ -4553,6 +3900,7 @@ SQLITE_API void sqlcipher_sqlite3_progress_handler(sqlcipher_sqlite3*, int, int(
** 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.
+** Use "ro" instead: "file:data.db?mode=ro".
** </table>
**
** ^URI hexadecimal escape sequences (%HH) are supported within the path and
@@ -4783,13 +4131,14 @@ SQLITE_API void sqlcipher_sqlite3_free_filename(char*);
** sqlcipher_sqlite3_extended_errcode() might change with each API call.
** Except, there are some interfaces that are guaranteed to never
** change the value of the error code. The error-code preserving
-** interfaces are:
+** interfaces include the following:
**
** <ul>
** <li> sqlcipher_sqlite3_errcode()
** <li> sqlcipher_sqlite3_extended_errcode()
** <li> sqlcipher_sqlite3_errmsg()
** <li> sqlcipher_sqlite3_errmsg16()
+** <li> sqlcipher_sqlite3_error_offset()
** </ul>
**
** ^The sqlcipher_sqlite3_errmsg() and sqlcipher_sqlite3_errmsg16() return English-language
@@ -4804,6 +4153,13 @@ SQLITE_API void sqlcipher_sqlite3_free_filename(char*);
** ^(Memory to hold the error message string is managed internally
** and must not be freed by the application)^.
**
+** ^If the most recent error references a specific token in the input
+** SQL, the sqlcipher_sqlite3_error_offset() interface returns the byte offset
+** of the start of that token. ^The byte offset returned by
+** sqlcipher_sqlite3_error_offset() assumes that the input SQL is UTF8.
+** ^If the most recent error does not reference a specific token in the input
+** SQL, then the sqlcipher_sqlite3_error_offset() function returns -1.
+**
** 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.
@@ -4823,6 +4179,7 @@ SQLITE_API int sqlcipher_sqlite3_extended_errcode(sqlcipher_sqlite3 *db);
SQLITE_API const char *sqlcipher_sqlite3_errmsg(sqlcipher_sqlite3*);
SQLITE_API const void *sqlcipher_sqlite3_errmsg16(sqlcipher_sqlite3*);
SQLITE_API const char *sqlcipher_sqlite3_errstr(int);
+SQLITE_API int sqlcipher_sqlite3_error_offset(sqlcipher_sqlite3 *db);
/*
** CAPI3REF: Prepared Statement Object
@@ -5180,12 +4537,17 @@ SQLITE_API int sqlcipher_sqlite3_prepare16_v3(
** are managed by SQLite and are automatically freed when the prepared
** statement is finalized.
** ^The string returned by sqlcipher_sqlite3_expanded_sql(P), on the other hand,
-** is obtained from [sqlcipher_sqlite3_malloc()] and must be free by the application
+** is obtained from [sqlcipher_sqlite3_malloc()] and must be freed by the application
** by passing it to [sqlcipher_sqlite3_free()].
+**
+** ^The sqlcipher_sqlite3_normalized_sql() interface is only available if
+** the [SQLITE_ENABLE_NORMALIZE] compile-time option is defined.
*/
SQLITE_API const char *sqlcipher_sqlite3_sql(sqlcipher_sqlite3_stmt *pStmt);
SQLITE_API char *sqlcipher_sqlite3_expanded_sql(sqlcipher_sqlite3_stmt *pStmt);
+#ifdef SQLITE_ENABLE_NORMALIZE
SQLITE_API const char *sqlcipher_sqlite3_normalized_sql(sqlcipher_sqlite3_stmt *pStmt);
+#endif
/*
** CAPI3REF: Determine If An SQL Statement Writes The Database
@@ -5220,6 +4582,19 @@ SQLITE_API const char *sqlcipher_sqlite3_normalized_sql(sqlcipher_sqlite3_stmt *
** [BEGIN] merely sets internal flags, but the [BEGIN|BEGIN IMMEDIATE] and
** [BEGIN|BEGIN EXCLUSIVE] commands do touch the database and so
** sqlcipher_sqlite3_stmt_readonly() returns false for those commands.
+**
+** ^This routine returns false if there is any possibility that the
+** statement might change the database file. ^A false return does
+** not guarantee that the statement will change the database file.
+** ^For example, an UPDATE statement might have a WHERE clause that
+** makes it a no-op, but the sqlcipher_sqlite3_stmt_readonly() result would still
+** be false. ^Similarly, a CREATE TABLE IF NOT EXISTS statement is a
+** read-only no-op if the table already exists, but
+** sqlcipher_sqlite3_stmt_readonly() still returns false for such a statement.
+**
+** ^If prepared statement X is an [EXPLAIN] or [EXPLAIN QUERY PLAN]
+** statement, then sqlcipher_sqlite3_stmt_readonly(X) returns the same value as
+** if the EXPLAIN or EXPLAIN QUERY PLAN prefix were omitted.
*/
SQLITE_API int sqlcipher_sqlite3_stmt_readonly(sqlcipher_sqlite3_stmt *pStmt);
@@ -5288,6 +4663,8 @@ SQLITE_API int sqlcipher_sqlite3_stmt_busy(sqlcipher_sqlite3_stmt*);
**
** ^The sqlcipher_sqlite3_value objects that are passed as parameters into the
** implementation of [application-defined SQL functions] are protected.
+** ^The sqlcipher_sqlite3_value objects returned by [sqlcipher_sqlite3_vtab_rhs_value()]
+** are protected.
** ^The sqlcipher_sqlite3_value object returned by
** [sqlcipher_sqlite3_column_value()] is unprotected.
** Unprotected sqlcipher_sqlite3_value objects may only be used as arguments
@@ -5389,18 +4766,22 @@ typedef struct sqlcipher_sqlite3_context sqlcipher_sqlite3_context;
** contain embedded NULs. The result of expressions involving strings
** with embedded NULs is undefined.
**
-** ^The fifth argument to the BLOB and string binding interfaces
-** is a destructor used to dispose of the BLOB or
-** string after SQLite has finished with it. ^The destructor is called
-** to dispose of the BLOB or string even if the call to the bind API fails,
-** except the destructor is not called if the third parameter is a NULL
-** pointer or the fourth parameter is negative.
-** ^If the fifth argument is
-** the special value [SQLITE_STATIC], then SQLite assumes that the
-** information is in static, unmanaged space and does not need to be freed.
-** ^If the fifth argument has the value [SQLITE_TRANSIENT], then
-** SQLite makes its own private copy of the data immediately, before
-** the sqlcipher_sqlite3_bind_*() routine returns.
+** ^The fifth argument to the BLOB and string binding interfaces controls
+** or indicates the lifetime of the object referenced by the third parameter.
+** These three options exist:
+** ^ (1) A destructor to dispose of the BLOB or string after SQLite has finished
+** with it may be passed. ^It is called to dispose of the BLOB or string even
+** if the call to the bind API fails, except the destructor is not called if
+** the third parameter is a NULL pointer or the fourth parameter is negative.
+** ^ (2) The special constant, [SQLITE_STATIC], may be passsed to indicate that
+** the application remains responsible for disposing of the object. ^In this
+** case, the object and the provided pointer to it must remain valid until
+** either the prepared statement is finalized or the same SQL parameter is
+** bound to something else, whichever occurs sooner.
+** ^ (3) The constant, [SQLITE_TRANSIENT], may be passed to indicate that the
+** object is to be copied prior to the return from sqlcipher_sqlite3_bind_*(). ^The
+** object and pointer to it must remain valid until then. ^SQLite will then
+** manage the lifetime of its private copy.
**
** ^The sixth argument to sqlcipher_sqlite3_bind_text64() must be one of
** [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE]
@@ -5905,6 +5286,10 @@ SQLITE_API int sqlcipher_sqlite3_data_count(sqlcipher_sqlite3_stmt *pStmt);
** even empty strings, are always zero-terminated. ^The return
** value from sqlcipher_sqlite3_column_blob() for a zero-length BLOB is a NULL pointer.
**
+** ^Strings returned by sqlcipher_sqlite3_column_text16() always have the endianness
+** which is native to the platform, regardless of the text encoding set
+** for the database.
+**
** <b>Warning:</b> ^The object returned by [sqlcipher_sqlite3_column_value()] is an
** [unprotected sqlcipher_sqlite3_value] object. In a multithreaded environment,
** an unprotected sqlcipher_sqlite3_value object may only be used safely with
@@ -5918,7 +5303,7 @@ SQLITE_API int sqlcipher_sqlite3_data_count(sqlcipher_sqlite3_stmt *pStmt);
** [application-defined SQL functions] or [virtual tables], not within
** top-level application code.
**
-** The these routines may attempt to convert the datatype of the result.
+** These routines may attempt to convert the datatype of the result.
** ^For example, if the internal representation is FLOAT and a text result
** is requested, [sqlcipher_sqlite3_snprintf()] is used internally to perform the
** conversion automatically. ^(The following table details the conversions
@@ -5943,7 +5328,7 @@ SQLITE_API int sqlcipher_sqlite3_data_count(sqlcipher_sqlite3_stmt *pStmt);
** <tr><td> TEXT <td> BLOB <td> No change
** <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
+** <tr><td> BLOB <td> TEXT <td> [CAST] to TEXT, ensure zero terminator
** </table>
** </blockquote>)^
**
@@ -6142,7 +5527,6 @@ SQLITE_API int sqlcipher_sqlite3_reset(sqlcipher_sqlite3_stmt *pStmt);
** within VIEWs, TRIGGERs, CHECK constraints, generated column expressions,
** index expressions, or the WHERE clause of partial indexes.
**
-** <span style="background-color:#ffff90;">
** For best security, the [SQLITE_DIRECTONLY] flag is recommended for
** all application-defined SQL functions that do not need to be
** used inside of triggers, view, CHECK constraints, or other elements of
@@ -6152,7 +5536,6 @@ SQLITE_API int sqlcipher_sqlite3_reset(sqlcipher_sqlite3_stmt *pStmt);
** a database file to include invocations of the function with parameters
** chosen by the attacker, which the application will then execute when
** the database file is opened and read.
-** </span>
**
** ^(The fifth parameter is an arbitrary pointer. The implementation of the
** function can gain access to this pointer using [sqlcipher_sqlite3_user_data()].)^
@@ -6517,7 +5900,8 @@ SQLITE_API unsigned int sqlcipher_sqlite3_value_subtype(sqlcipher_sqlite3_value*
** object D and returns a pointer to that copy. ^The [sqlcipher_sqlite3_value] returned
** is a [protected sqlcipher_sqlite3_value] object even if the input is not.
** ^The sqlcipher_sqlite3_value_dup(V) interface returns NULL if V is NULL or if a
-** memory allocation fails.
+** memory allocation fails. ^If V is a [pointer value], then the result
+** of sqlcipher_sqlite3_value_dup(V) is a NULL value.
**
** ^The sqlcipher_sqlite3_value_free(V) interface frees an [sqlcipher_sqlite3_value] object
** previously obtained from [sqlcipher_sqlite3_value_dup()]. ^If V is a NULL pointer
@@ -7030,6 +6414,19 @@ SQLITE_API int sqlcipher_sqlite3_key_v2(
** The code to implement this API is not available in the public release
** of SQLite.
*/
+/* SQLCipher usage note:
+
+ If the current database is plaintext SQLCipher will NOT encrypt it.
+ If the current database is encrypted and pNew==0 or nNew==0, SQLCipher
+ will NOT decrypt it.
+
+ This routine will ONLY work on an already encrypted database in order
+ to change the key.
+
+ Conversion from plaintext-to-encrypted or encrypted-to-plaintext should
+ use an ATTACHed database and the sqlcipher_export() convenience function
+ as per the SQLCipher Documentation.
+*/
SQLITE_API int sqlcipher_sqlite3_rekey(
sqlcipher_sqlite3 *db, /* Database to be rekeyed */
const void *pKey, int nKey /* The new key */
@@ -7247,6 +6644,28 @@ SQLITE_API int sqlcipher_sqlite3_get_autocommit(sqlcipher_sqlite3*);
SQLITE_API sqlcipher_sqlite3 *sqlcipher_sqlite3_db_handle(sqlcipher_sqlite3_stmt*);
/*
+** CAPI3REF: Return The Schema Name For A Database Connection
+** METHOD: sqlcipher_sqlite3
+**
+** ^The sqlcipher_sqlite3_db_name(D,N) interface returns a pointer to the schema name
+** for the N-th database on database connection D, or a NULL pointer of N is
+** out of range. An N value of 0 means the main database file. An N of 1 is
+** the "temp" schema. Larger values of N correspond to various ATTACH-ed
+** databases.
+**
+** Space to hold the string that is returned by sqlcipher_sqlite3_db_name() is managed
+** by SQLite itself. The string might be deallocated by any operation that
+** changes the schema, including [ATTACH] or [DETACH] or calls to
+** [sqlcipher_sqlite3_serialize()] or [sqlcipher_sqlite3_deserialize()], even operations that
+** occur on a different thread. Applications that need to
+** remember the string long-term should make their own copy. Applications that
+** are accessing the same database connection simultaneously on multiple
+** threads should mutex-protect calls to this API and should make their own
+** private copy of the result prior to releasing the mutex.
+*/
+SQLITE_API const char *sqlcipher_sqlite3_db_name(sqlcipher_sqlite3 *db, int N);
+
+/*
** CAPI3REF: Return The Filename For A Database Connection
** METHOD: sqlcipher_sqlite3
**
@@ -7406,6 +6825,72 @@ SQLITE_API void *sqlcipher_sqlite3_commit_hook(sqlcipher_sqlite3*, int(*)(void*)
SQLITE_API void *sqlcipher_sqlite3_rollback_hook(sqlcipher_sqlite3*, void(*)(void *), void*);
/*
+** CAPI3REF: Autovacuum Compaction Amount Callback
+** METHOD: sqlcipher_sqlite3
+**
+** ^The sqlcipher_sqlite3_autovacuum_pages(D,C,P,X) interface registers a callback
+** function C that is invoked prior to each autovacuum of the database
+** file. ^The callback is passed a copy of the generic data pointer (P),
+** the schema-name of the attached database that is being autovacuumed,
+** the the size of the database file in pages, the number of free pages,
+** and the number of bytes per page, respectively. The callback should
+** return the number of free pages that should be removed by the
+** autovacuum. ^If the callback returns zero, then no autovacuum happens.
+** ^If the value returned is greater than or equal to the number of
+** free pages, then a complete autovacuum happens.
+**
+** <p>^If there are multiple ATTACH-ed database files that are being
+** modified as part of a transaction commit, then the autovacuum pages
+** callback is invoked separately for each file.
+**
+** <p><b>The callback is not reentrant.</b> The callback function should
+** not attempt to invoke any other SQLite interface. If it does, bad
+** things may happen, including segmentation faults and corrupt database
+** files. The callback function should be a simple function that
+** does some arithmetic on its input parameters and returns a result.
+**
+** ^The X parameter to sqlcipher_sqlite3_autovacuum_pages(D,C,P,X) is an optional
+** destructor for the P parameter. ^If X is not NULL, then X(P) is
+** invoked whenever the database connection closes or when the callback
+** is overwritten by another invocation of sqlcipher_sqlite3_autovacuum_pages().
+**
+** <p>^There is only one autovacuum pages callback per database connection.
+** ^Each call to the sqlcipher_sqlite3_autovacuum_pages() interface overrides all
+** previous invocations for that database connection. ^If the callback
+** argument (C) to sqlcipher_sqlite3_autovacuum_pages(D,C,P,X) is a NULL pointer,
+** then the autovacuum steps callback is cancelled. The return value
+** from sqlcipher_sqlite3_autovacuum_pages() is normally SQLITE_OK, but might
+** be some other error code if something goes wrong. The current
+** implementation will only return SQLITE_OK or SQLITE_MISUSE, but other
+** return codes might be added in future releases.
+**
+** <p>If no autovacuum pages callback is specified (the usual case) or
+** a NULL pointer is provided for the callback,
+** then the default behavior is to vacuum all free pages. So, in other
+** words, the default behavior is the same as if the callback function
+** were something like this:
+**
+** <blockquote><pre>
+** &nbsp; unsigned int demonstration_autovac_pages_callback(
+** &nbsp; void *pClientData,
+** &nbsp; const char *zSchema,
+** &nbsp; unsigned int nDbPage,
+** &nbsp; unsigned int nFreePage,
+** &nbsp; unsigned int nBytePerPage
+** &nbsp; ){
+** &nbsp; return nFreePage;
+** &nbsp; }
+** </pre></blockquote>
+*/
+SQLITE_API int sqlcipher_sqlite3_autovacuum_pages(
+ sqlcipher_sqlite3 *db,
+ unsigned int(*)(void*,const char*,unsigned int,unsigned int,unsigned int),
+ void*,
+ void(*)(void*)
+);
+
+
+/*
** CAPI3REF: Data Change Notification Callbacks
** METHOD: sqlcipher_sqlite3
**
@@ -8046,24 +7531,56 @@ struct sqlcipher_sqlite3_index_info {
**
** These macros define the allowed values for the
** [sqlcipher_sqlite3_index_info].aConstraint[].op field. Each value represents
-** an operator that is part of a constraint term in the wHERE clause of
+** an operator that is part of a constraint term in the WHERE clause of
** a query that uses a [virtual table].
-*/
-#define SQLITE_INDEX_CONSTRAINT_EQ 2
-#define SQLITE_INDEX_CONSTRAINT_GT 4
-#define SQLITE_INDEX_CONSTRAINT_LE 8
-#define SQLITE_INDEX_CONSTRAINT_LT 16
-#define SQLITE_INDEX_CONSTRAINT_GE 32
-#define SQLITE_INDEX_CONSTRAINT_MATCH 64
-#define SQLITE_INDEX_CONSTRAINT_LIKE 65
-#define SQLITE_INDEX_CONSTRAINT_GLOB 66
-#define SQLITE_INDEX_CONSTRAINT_REGEXP 67
-#define SQLITE_INDEX_CONSTRAINT_NE 68
-#define SQLITE_INDEX_CONSTRAINT_ISNOT 69
-#define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70
-#define SQLITE_INDEX_CONSTRAINT_ISNULL 71
-#define SQLITE_INDEX_CONSTRAINT_IS 72
-#define SQLITE_INDEX_CONSTRAINT_FUNCTION 150
+**
+** ^The left-hand operand of the operator is given by the corresponding
+** aConstraint[].iColumn field. ^An iColumn of -1 indicates the left-hand
+** operand is the rowid.
+** The SQLITE_INDEX_CONSTRAINT_LIMIT and SQLITE_INDEX_CONSTRAINT_OFFSET
+** operators have no left-hand operand, and so for those operators the
+** corresponding aConstraint[].iColumn is meaningless and should not be
+** used.
+**
+** All operator values from SQLITE_INDEX_CONSTRAINT_FUNCTION through
+** value 255 are reserved to represent functions that are overloaded
+** by the [xFindFunction|xFindFunction method] of the virtual table
+** implementation.
+**
+** The right-hand operands for each constraint might be accessible using
+** the [sqlcipher_sqlite3_vtab_rhs_value()] interface. Usually the right-hand
+** operand is only available if it appears as a single constant literal
+** in the input SQL. If the right-hand operand is another column or an
+** expression (even a constant expression) or a parameter, then the
+** sqlcipher_sqlite3_vtab_rhs_value() probably will not be able to extract it.
+** ^The SQLITE_INDEX_CONSTRAINT_ISNULL and
+** SQLITE_INDEX_CONSTRAINT_ISNOTNULL operators have no right-hand operand
+** and hence calls to sqlcipher_sqlite3_vtab_rhs_value() for those operators will
+** always return SQLITE_NOTFOUND.
+**
+** The collating sequence to be used for comparison can be found using
+** the [sqlcipher_sqlite3_vtab_collation()] interface. For most real-world virtual
+** tables, the collating sequence of constraints does not matter (for example
+** because the constraints are numeric) and so the sqlcipher_sqlite3_vtab_collation()
+** interface is no commonly needed.
+*/
+#define SQLITE_INDEX_CONSTRAINT_EQ 2
+#define SQLITE_INDEX_CONSTRAINT_GT 4
+#define SQLITE_INDEX_CONSTRAINT_LE 8
+#define SQLITE_INDEX_CONSTRAINT_LT 16
+#define SQLITE_INDEX_CONSTRAINT_GE 32
+#define SQLITE_INDEX_CONSTRAINT_MATCH 64
+#define SQLITE_INDEX_CONSTRAINT_LIKE 65
+#define SQLITE_INDEX_CONSTRAINT_GLOB 66
+#define SQLITE_INDEX_CONSTRAINT_REGEXP 67
+#define SQLITE_INDEX_CONSTRAINT_NE 68
+#define SQLITE_INDEX_CONSTRAINT_ISNOT 69
+#define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70
+#define SQLITE_INDEX_CONSTRAINT_ISNULL 71
+#define SQLITE_INDEX_CONSTRAINT_IS 72
+#define SQLITE_INDEX_CONSTRAINT_LIMIT 73
+#define SQLITE_INDEX_CONSTRAINT_OFFSET 74
+#define SQLITE_INDEX_CONSTRAINT_FUNCTION 150
/*
** CAPI3REF: Register A Virtual Table Implementation
@@ -8092,7 +7609,7 @@ struct sqlcipher_sqlite3_index_info {
** destructor.
**
** ^If the third parameter (the pointer to the sqlcipher_sqlite3_module object) is
-** NULL then no new module is create and any existing modules with the
+** NULL then no new module is created and any existing modules with the
** same name are dropped.
**
** See also: [sqlcipher_sqlite3_drop_modules()]
@@ -8866,7 +8383,10 @@ SQLITE_API int sqlcipher_sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_PRNG_SEED 28
#define SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS 29
#define SQLITE_TESTCTRL_SEEK_COUNT 30
-#define SQLITE_TESTCTRL_LAST 30 /* Largest TESTCTRL */
+#define SQLITE_TESTCTRL_TRACEFLAGS 31
+#define SQLITE_TESTCTRL_TUNE 32
+#define SQLITE_TESTCTRL_LOGEST 33
+#define SQLITE_TESTCTRL_LAST 33 /* Largest TESTCTRL */
/*
** CAPI3REF: SQL Keyword Checking
@@ -9389,6 +8909,16 @@ SQLITE_API int sqlcipher_sqlite3_stmt_status(sqlcipher_sqlite3_stmt*, int op,int
** The counter is incremented on the first [sqlcipher_sqlite3_step()] call of each
** cycle.
**
+** [[SQLITE_STMTSTATUS_FILTER_MISS]]
+** [[SQLITE_STMTSTATUS_FILTER HIT]]
+** <dt>SQLITE_STMTSTATUS_FILTER_HIT<br>
+** SQLITE_STMTSTATUS_FILTER_MISS</dt>
+** <dd>^SQLITE_STMTSTATUS_FILTER_HIT is the number of times that a join
+** step was bypassed because a Bloom filter returned not-found. The
+** corresponding SQLITE_STMTSTATUS_FILTER_MISS value is the number of
+** times that the Bloom filter returned a find, and thus the join step
+** had to be processed as normal.
+**
** [[SQLITE_STMTSTATUS_MEMUSED]] <dt>SQLITE_STMTSTATUS_MEMUSED</dt>
** <dd>^This is the approximate number of bytes of heap memory
** used to store the prepared statement. ^This value is not actually
@@ -9403,6 +8933,8 @@ SQLITE_API int sqlcipher_sqlite3_stmt_status(sqlcipher_sqlite3_stmt*, int op,int
#define SQLITE_STMTSTATUS_VM_STEP 4
#define SQLITE_STMTSTATUS_REPREPARE 5
#define SQLITE_STMTSTATUS_RUN 6
+#define SQLITE_STMTSTATUS_FILTER_MISS 7
+#define SQLITE_STMTSTATUS_FILTER_HIT 8
#define SQLITE_STMTSTATUS_MEMUSED 99
/*
@@ -10066,8 +9598,9 @@ SQLITE_API void sqlcipher_sqlite3_log(int iErrCode, const char *zFormat, ...);
**
** A single database handle may have at most a single write-ahead log callback
** registered at one time. ^Calling [sqlcipher_sqlite3_wal_hook()] replaces any
-** previously registered write-ahead log callback. ^Note that the
-** [sqlcipher_sqlite3_wal_autocheckpoint()] interface and the
+** previously registered write-ahead log callback. ^The return value is
+** a copy of the third parameter from the previous call, if any, or 0.
+** ^Note that the [sqlcipher_sqlite3_wal_autocheckpoint()] interface and the
** [wal_autocheckpoint pragma] both invoke [sqlcipher_sqlite3_wal_hook()] and will
** overwrite any prior [sqlcipher_sqlite3_wal_hook()] settings.
*/
@@ -10370,20 +9903,277 @@ SQLITE_API int sqlcipher_sqlite3_vtab_nochange(sqlcipher_sqlite3_context*);
/*
** CAPI3REF: Determine The Collation For a Virtual Table Constraint
+** METHOD: sqlcipher_sqlite3_index_info
**
** This function may only be called from within a call to the [xBestIndex]
-** method of a [virtual table].
+** method of a [virtual table]. This function returns a pointer to a string
+** that is the name of the appropriate collation sequence to use for text
+** comparisons on the constraint identified by its arguments.
**
-** The first argument must be the sqlcipher_sqlite3_index_info object that is the
-** first parameter to the xBestIndex() method. The second argument must be
-** an index into the aConstraint[] array belonging to the sqlcipher_sqlite3_index_info
-** structure passed to xBestIndex. This function returns a pointer to a buffer
-** containing the name of the collation sequence for the corresponding
-** constraint.
+** The first argument must be the pointer to the [sqlcipher_sqlite3_index_info] object
+** that is the first parameter to the xBestIndex() method. The second argument
+** must be an index into the aConstraint[] array belonging to the
+** sqlcipher_sqlite3_index_info structure passed to xBestIndex.
+**
+** Important:
+** The first parameter must be the same pointer that is passed into the
+** xBestMethod() method. The first parameter may not be a pointer to a
+** different [sqlcipher_sqlite3_index_info] object, even an exact copy.
+**
+** The return value is computed as follows:
+**
+** <ol>
+** <li><p> If the constraint comes from a WHERE clause expression that contains
+** a [COLLATE operator], then the name of the collation specified by
+** that COLLATE operator is returned.
+** <li><p> If there is no COLLATE operator, but the column that is the subject
+** of the constraint specifies an alternative collating sequence via
+** a [COLLATE clause] on the column definition within the CREATE TABLE
+** statement that was passed into [sqlcipher_sqlite3_declare_vtab()], then the
+** name of that alternative collating sequence is returned.
+** <li><p> Otherwise, "BINARY" is returned.
+** </ol>
*/
SQLITE_API SQLITE_EXPERIMENTAL const char *sqlcipher_sqlite3_vtab_collation(sqlcipher_sqlite3_index_info*,int);
/*
+** CAPI3REF: Determine if a virtual table query is DISTINCT
+** METHOD: sqlcipher_sqlite3_index_info
+**
+** This API may only be used from within an [xBestIndex|xBestIndex method]
+** of a [virtual table] implementation. The result of calling this
+** interface from outside of xBestIndex() is undefined and probably harmful.
+**
+** ^The sqlcipher_sqlite3_vtab_distinct() interface returns an integer between 0 and
+** 3. The integer returned by sqlcipher_sqlite3_vtab_distinct()
+** gives the virtual table additional information about how the query
+** planner wants the output to be ordered. As long as the virtual table
+** can meet the ordering requirements of the query planner, it may set
+** the "orderByConsumed" flag.
+**
+** <ol><li value="0"><p>
+** ^If the sqlcipher_sqlite3_vtab_distinct() interface returns 0, that means
+** that the query planner needs the virtual table to return all rows in the
+** sort order defined by the "nOrderBy" and "aOrderBy" fields of the
+** [sqlcipher_sqlite3_index_info] object. This is the default expectation. If the
+** virtual table outputs all rows in sorted order, then it is always safe for
+** the xBestIndex method to set the "orderByConsumed" flag, regardless of
+** the return value from sqlcipher_sqlite3_vtab_distinct().
+** <li value="1"><p>
+** ^(If the sqlcipher_sqlite3_vtab_distinct() interface returns 1, that means
+** that the query planner does not need the rows to be returned in sorted order
+** as long as all rows with the same values in all columns identified by the
+** "aOrderBy" field are adjacent.)^ This mode is used when the query planner
+** is doing a GROUP BY.
+** <li value="2"><p>
+** ^(If the sqlcipher_sqlite3_vtab_distinct() interface returns 2, that means
+** that the query planner does not need the rows returned in any particular
+** order, as long as rows with the same values in all "aOrderBy" columns
+** are adjacent.)^ ^(Furthermore, only a single row for each particular
+** combination of values in the columns identified by the "aOrderBy" field
+** needs to be returned.)^ ^It is always ok for two or more rows with the same
+** values in all "aOrderBy" columns to be returned, as long as all such rows
+** are adjacent. ^The virtual table may, if it chooses, omit extra rows
+** that have the same value for all columns identified by "aOrderBy".
+** ^However omitting the extra rows is optional.
+** This mode is used for a DISTINCT query.
+** <li value="3"><p>
+** ^(If the sqlcipher_sqlite3_vtab_distinct() interface returns 3, that means
+** that the query planner needs only distinct rows but it does need the
+** rows to be sorted.)^ ^The virtual table implementation is free to omit
+** rows that are identical in all aOrderBy columns, if it wants to, but
+** it is not required to omit any rows. This mode is used for queries
+** that have both DISTINCT and ORDER BY clauses.
+** </ol>
+**
+** ^For the purposes of comparing virtual table output values to see if the
+** values are same value for sorting purposes, two NULL values are considered
+** to be the same. In other words, the comparison operator is "IS"
+** (or "IS NOT DISTINCT FROM") and not "==".
+**
+** If a virtual table implementation is unable to meet the requirements
+** specified above, then it must not set the "orderByConsumed" flag in the
+** [sqlcipher_sqlite3_index_info] object or an incorrect answer may result.
+**
+** ^A virtual table implementation is always free to return rows in any order
+** it wants, as long as the "orderByConsumed" flag is not set. ^When the
+** the "orderByConsumed" flag is unset, the query planner will add extra
+** [bytecode] to ensure that the final results returned by the SQL query are
+** ordered correctly. The use of the "orderByConsumed" flag and the
+** sqlcipher_sqlite3_vtab_distinct() interface is merely an optimization. ^Careful
+** use of the sqlcipher_sqlite3_vtab_distinct() interface and the "orderByConsumed"
+** flag might help queries against a virtual table to run faster. Being
+** overly aggressive and setting the "orderByConsumed" flag when it is not
+** valid to do so, on the other hand, might cause SQLite to return incorrect
+** results.
+*/
+SQLITE_API int sqlcipher_sqlite3_vtab_distinct(sqlcipher_sqlite3_index_info*);
+
+/*
+** CAPI3REF: Identify and handle IN constraints in xBestIndex
+**
+** This interface may only be used from within an
+** [xBestIndex|xBestIndex() method] of a [virtual table] implementation.
+** The result of invoking this interface from any other context is
+** undefined and probably harmful.
+**
+** ^(A constraint on a virtual table of the form
+** "[IN operator|column IN (...)]" is
+** communicated to the xBestIndex method as a
+** [SQLITE_INDEX_CONSTRAINT_EQ] constraint.)^ If xBestIndex wants to use
+** this constraint, it must set the corresponding
+** aConstraintUsage[].argvIndex to a postive integer. ^(Then, under
+** the usual mode of handling IN operators, SQLite generates [bytecode]
+** that invokes the [xFilter|xFilter() method] once for each value
+** on the right-hand side of the IN operator.)^ Thus the virtual table
+** only sees a single value from the right-hand side of the IN operator
+** at a time.
+**
+** In some cases, however, it would be advantageous for the virtual
+** table to see all values on the right-hand of the IN operator all at
+** once. The sqlcipher_sqlite3_vtab_in() interfaces facilitates this in two ways:
+**
+** <ol>
+** <li><p>
+** ^A call to sqlcipher_sqlite3_vtab_in(P,N,-1) will return true (non-zero)
+** if and only if the [sqlcipher_sqlite3_index_info|P->aConstraint][N] constraint
+** is an [IN operator] that can be processed all at once. ^In other words,
+** sqlcipher_sqlite3_vtab_in() with -1 in the third argument is a mechanism
+** by which the virtual table can ask SQLite if all-at-once processing
+** of the IN operator is even possible.
+**
+** <li><p>
+** ^A call to sqlcipher_sqlite3_vtab_in(P,N,F) with F==1 or F==0 indicates
+** to SQLite that the virtual table does or does not want to process
+** the IN operator all-at-once, respectively. ^Thus when the third
+** parameter (F) is non-negative, this interface is the mechanism by
+** which the virtual table tells SQLite how it wants to process the
+** IN operator.
+** </ol>
+**
+** ^The sqlcipher_sqlite3_vtab_in(P,N,F) interface can be invoked multiple times
+** within the same xBestIndex method call. ^For any given P,N pair,
+** the return value from sqlcipher_sqlite3_vtab_in(P,N,F) will always be the same
+** within the same xBestIndex call. ^If the interface returns true
+** (non-zero), that means that the constraint is an IN operator
+** that can be processed all-at-once. ^If the constraint is not an IN
+** operator or cannot be processed all-at-once, then the interface returns
+** false.
+**
+** ^(All-at-once processing of the IN operator is selected if both of the
+** following conditions are met:
+**
+** <ol>
+** <li><p> The P->aConstraintUsage[N].argvIndex value is set to a positive
+** integer. This is how the virtual table tells SQLite that it wants to
+** use the N-th constraint.
+**
+** <li><p> The last call to sqlcipher_sqlite3_vtab_in(P,N,F) for which F was
+** non-negative had F>=1.
+** </ol>)^
+**
+** ^If either or both of the conditions above are false, then SQLite uses
+** the traditional one-at-a-time processing strategy for the IN constraint.
+** ^If both conditions are true, then the argvIndex-th parameter to the
+** xFilter method will be an [sqlcipher_sqlite3_value] that appears to be NULL,
+** but which can be passed to [sqlcipher_sqlite3_vtab_in_first()] and
+** [sqlcipher_sqlite3_vtab_in_next()] to find all values on the right-hand side
+** of the IN constraint.
+*/
+SQLITE_API int sqlcipher_sqlite3_vtab_in(sqlcipher_sqlite3_index_info*, int iCons, int bHandle);
+
+/*
+** CAPI3REF: Find all elements on the right-hand side of an IN constraint.
+**
+** These interfaces are only useful from within the
+** [xFilter|xFilter() method] of a [virtual table] implementation.
+** The result of invoking these interfaces from any other context
+** is undefined and probably harmful.
+**
+** The X parameter in a call to sqlcipher_sqlite3_vtab_in_first(X,P) or
+** sqlcipher_sqlite3_vtab_in_next(X,P) must be one of the parameters to the
+** xFilter method which invokes these routines, and specifically
+** a parameter that was previously selected for all-at-once IN constraint
+** processing use the [sqlcipher_sqlite3_vtab_in()] interface in the
+** [xBestIndex|xBestIndex method]. ^(If the X parameter is not
+** an xFilter argument that was selected for all-at-once IN constraint
+** processing, then these routines return [SQLITE_MISUSE])^ or perhaps
+** exhibit some other undefined or harmful behavior.
+**
+** ^(Use these routines to access all values on the right-hand side
+** of the IN constraint using code like the following:
+**
+** <blockquote><pre>
+** &nbsp; for(rc=sqlcipher_sqlite3_vtab_in_first(pList, &pVal);
+** &nbsp; rc==SQLITE_OK && pVal
+** &nbsp; rc=sqlcipher_sqlite3_vtab_in_next(pList, &pVal)
+** &nbsp; ){
+** &nbsp; // do something with pVal
+** &nbsp; }
+** &nbsp; if( rc!=SQLITE_OK ){
+** &nbsp; // an error has occurred
+** &nbsp; }
+** </pre></blockquote>)^
+**
+** ^On success, the sqlcipher_sqlite3_vtab_in_first(X,P) and sqlcipher_sqlite3_vtab_in_next(X,P)
+** routines return SQLITE_OK and set *P to point to the first or next value
+** on the RHS of the IN constraint. ^If there are no more values on the
+** right hand side of the IN constraint, then *P is set to NULL and these
+** routines return [SQLITE_DONE]. ^The return value might be
+** some other value, such as SQLITE_NOMEM, in the event of a malfunction.
+**
+** The *ppOut values returned by these routines are only valid until the
+** next call to either of these routines or until the end of the xFilter
+** method from which these routines were called. If the virtual table
+** implementation needs to retain the *ppOut values for longer, it must make
+** copies. The *ppOut values are [protected sqlcipher_sqlite3_value|protected].
+*/
+SQLITE_API int sqlcipher_sqlite3_vtab_in_first(sqlcipher_sqlite3_value *pVal, sqlcipher_sqlite3_value **ppOut);
+SQLITE_API int sqlcipher_sqlite3_vtab_in_next(sqlcipher_sqlite3_value *pVal, sqlcipher_sqlite3_value **ppOut);
+
+/*
+** CAPI3REF: Constraint values in xBestIndex()
+** METHOD: sqlcipher_sqlite3_index_info
+**
+** This API may only be used from within the [xBestIndex|xBestIndex method]
+** of a [virtual table] implementation. The result of calling this interface
+** from outside of an xBestIndex method are undefined and probably harmful.
+**
+** ^When the sqlcipher_sqlite3_vtab_rhs_value(P,J,V) interface is invoked from within
+** the [xBestIndex] method of a [virtual table] implementation, with P being
+** a copy of the [sqlcipher_sqlite3_index_info] object pointer passed into xBestIndex and
+** J being a 0-based index into P->aConstraint[], then this routine
+** attempts to set *V to the value of the right-hand operand of
+** that constraint if the right-hand operand is known. ^If the
+** right-hand operand is not known, then *V is set to a NULL pointer.
+** ^The sqlcipher_sqlite3_vtab_rhs_value(P,J,V) interface returns SQLITE_OK if
+** and only if *V is set to a value. ^The sqlcipher_sqlite3_vtab_rhs_value(P,J,V)
+** inteface returns SQLITE_NOTFOUND if the right-hand side of the J-th
+** constraint is not available. ^The sqlcipher_sqlite3_vtab_rhs_value() interface
+** can return an result code other than SQLITE_OK or SQLITE_NOTFOUND if
+** something goes wrong.
+**
+** The sqlcipher_sqlite3_vtab_rhs_value() interface is usually only successful if
+** the right-hand operand of a constraint is a literal value in the original
+** SQL statement. If the right-hand operand is an expression or a reference
+** to some other column or a [host parameter], then sqlcipher_sqlite3_vtab_rhs_value()
+** will probably return [SQLITE_NOTFOUND].
+**
+** ^(Some constraints, such as [SQLITE_INDEX_CONSTRAINT_ISNULL] and
+** [SQLITE_INDEX_CONSTRAINT_ISNOTNULL], have no right-hand operand. For such
+** constraints, sqlcipher_sqlite3_vtab_rhs_value() always returns SQLITE_NOTFOUND.)^
+**
+** ^The [sqlcipher_sqlite3_value] object returned in *V is a protected sqlcipher_sqlite3_value
+** and remains valid for the duration of the xBestIndex method call.
+** ^When xBestIndex returns, the sqlcipher_sqlite3_value object returned by
+** sqlcipher_sqlite3_vtab_rhs_value() is automatically deallocated.
+**
+** The "_rhs_" in the name of this routine is an abbreviation for
+** "Right-Hand Side".
+*/
+SQLITE_API int sqlcipher_sqlite3_vtab_rhs_value(sqlcipher_sqlite3_index_info*, int, sqlcipher_sqlite3_value **ppVal);
+
+/*
** CAPI3REF: Conflict resolution modes
** KEYWORDS: {conflict resolution mode}
**
@@ -10618,6 +10408,15 @@ SQLITE_API int sqlcipher_sqlite3_db_cacheflush(sqlcipher_sqlite3*);
** triggers; or 2 for changes resulting from triggers called by top-level
** triggers; and so forth.
**
+** When the [sqlcipher_sqlite3_blob_write()] API is used to update a blob column,
+** the pre-update hook is invoked with SQLITE_DELETE. This is because the
+** in this case the new values are not available. In this case, when a
+** callback made with op==SQLITE_DELETE is actuall a write using the
+** sqlcipher_sqlite3_blob_write() API, the [sqlcipher_sqlite3_preupdate_blobwrite()] returns
+** the index of the column being written. In other cases, where the
+** pre-update hook is being invoked for some other reason, including a
+** regular DELETE, sqlcipher_sqlite3_preupdate_blobwrite() returns -1.
+**
** See also: [sqlcipher_sqlite3_update_hook()]
*/
#if defined(SQLITE_ENABLE_PREUPDATE_HOOK)
@@ -10638,6 +10437,7 @@ SQLITE_API int sqlcipher_sqlite3_preupdate_old(sqlcipher_sqlite3 *, int, sqlciph
SQLITE_API int sqlcipher_sqlite3_preupdate_count(sqlcipher_sqlite3 *);
SQLITE_API int sqlcipher_sqlite3_preupdate_depth(sqlcipher_sqlite3 *);
SQLITE_API int sqlcipher_sqlite3_preupdate_new(sqlcipher_sqlite3 *, int, sqlcipher_sqlite3_value **);
+SQLITE_API int sqlcipher_sqlite3_preupdate_blobwrite(sqlcipher_sqlite3 *);
#endif
/*
@@ -10876,8 +10676,8 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlcipher_sqlite3_snapshot_recover(sqlcipher_
** SQLITE_SERIALIZE_NOCOPY bit is omitted from argument F if a memory
** allocation error occurs.
**
-** This interface is only available if SQLite is compiled with the
-** [SQLITE_ENABLE_DESERIALIZE] option.
+** This interface is omitted if SQLite is compiled with the
+** [SQLITE_OMIT_DESERIALIZE] option.
*/
SQLITE_API unsigned char *sqlcipher_sqlite3_serialize(
sqlcipher_sqlite3 *db, /* The database connection */
@@ -10924,12 +10724,16 @@ SQLITE_API unsigned char *sqlcipher_sqlite3_serialize(
** database is currently in a read transaction or is involved in a backup
** operation.
**
+** It is not possible to deserialized into the TEMP database. If the
+** S argument to sqlcipher_sqlite3_deserialize(D,S,P,N,M,F) is "temp" then the
+** function returns SQLITE_ERROR.
+**
** If sqlcipher_sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the
** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then
** [sqlcipher_sqlite3_free()] is invoked on argument P prior to returning.
**
-** This interface is only available if SQLite is compiled with the
-** [SQLITE_ENABLE_DESERIALIZE] option.
+** This interface is omitted if SQLite is compiled with the
+** [SQLITE_OMIT_DESERIALIZE] option.
*/
SQLITE_API int sqlcipher_sqlite3_deserialize(
sqlcipher_sqlite3 *db, /* The database connection */
@@ -11178,6 +10982,38 @@ SQLITE_API int sqlcipher_sqlite3session_create(
*/
SQLITE_API void sqlcipher_sqlite3session_delete(sqlcipher_sqlite3_session *pSession);
+/*
+** CAPIREF: Conigure a Session Object
+** METHOD: sqlcipher_sqlite3_session
+**
+** This method is used to configure a session object after it has been
+** created. At present the only valid value for the second parameter is
+** [SQLITE_SESSION_OBJCONFIG_SIZE].
+**
+** Arguments for sqlcipher_sqlite3session_object_config()
+**
+** The following values may passed as the the 4th parameter to
+** sqlcipher_sqlite3session_object_config().
+**
+** <dt>SQLITE_SESSION_OBJCONFIG_SIZE <dd>
+** This option is used to set, clear or query the flag that enables
+** the [sqlcipher_sqlite3session_changeset_size()] API. Because it imposes some
+** computational overhead, this API is disabled by default. Argument
+** pArg must point to a value of type (int). If the value is initially
+** 0, then the sqlcipher_sqlite3session_changeset_size() API is disabled. If it
+** is greater than 0, then the same API is enabled. Or, if the initial
+** value is less than zero, no change is made. In all cases the (int)
+** variable is set to 1 if the sqlcipher_sqlite3session_changeset_size() API is
+** enabled following the current call, or 0 otherwise.
+**
+** It is an error (SQLITE_MISUSE) to attempt to modify this setting after
+** the first table has been attached to the session object.
+*/
+SQLITE_API int sqlcipher_sqlite3session_object_config(sqlcipher_sqlite3_session*, int op, void *pArg);
+
+/*
+*/
+#define SQLITE_SESSION_OBJCONFIG_SIZE 1
/*
** CAPI3REF: Enable Or Disable A Session Object
@@ -11423,6 +11259,22 @@ SQLITE_API int sqlcipher_sqlite3session_changeset(
);
/*
+** CAPI3REF: Return An Upper-limit For The Size Of The Changeset
+** METHOD: sqlcipher_sqlite3_session
+**
+** By default, this function always returns 0. For it to return
+** a useful result, the sqlcipher_sqlite3_session object must have been configured
+** to enable this API using sqlcipher_sqlite3session_object_config() with the
+** SQLITE_SESSION_OBJCONFIG_SIZE verb.
+**
+** When enabled, this function returns an upper limit, in bytes, for the size
+** of the changeset that might be produced if sqlcipher_sqlite3session_changeset() were
+** called. The final changeset size might be equal to or smaller than the
+** size in bytes returned by this function.
+*/
+SQLITE_API sqlcipher_sqlite3_int64 sqlcipher_sqlite3session_changeset_size(sqlcipher_sqlite3_session *pSession);
+
+/*
** CAPI3REF: Load The Difference Between Tables Into A Session
** METHOD: sqlcipher_sqlite3_session
**
@@ -11540,6 +11392,14 @@ SQLITE_API int sqlcipher_sqlite3session_patchset(
SQLITE_API int sqlcipher_sqlite3session_isempty(sqlcipher_sqlite3_session *pSession);
/*
+** CAPI3REF: Query for the amount of heap memory used by a session object.
+**
+** This API returns the total amount of heap memory in bytes currently
+** used by the session object passed as the only argument.
+*/
+SQLITE_API sqlcipher_sqlite3_int64 sqlcipher_sqlite3session_memory_used(sqlcipher_sqlite3_session *pSession);
+
+/*
** CAPI3REF: Create An Iterator To Traverse A Changeset
** CONSTRUCTOR: sqlcipher_sqlite3_changeset_iter
**
@@ -11641,18 +11501,23 @@ SQLITE_API int sqlcipher_sqlite3changeset_next(sqlcipher_sqlite3_changeset_iter
** call to [sqlcipher_sqlite3changeset_next()] must have returned [SQLITE_ROW]. If this
** is not the case, this function returns [SQLITE_MISUSE].
**
-** If argument pzTab is not NULL, then *pzTab is set to point to a
-** nul-terminated utf-8 encoded string containing the name of the table
-** affected by the current change. The buffer remains valid until either
-** sqlcipher_sqlite3changeset_next() is called on the iterator or until the
-** conflict-handler function returns. If pnCol is not NULL, then *pnCol is
-** set to the number of columns in the table affected by the change. If
-** pbIndirect is not NULL, then *pbIndirect is set to true (1) if the change
+** Arguments pOp, pnCol and pzTab may not be NULL. Upon return, three
+** outputs are set through these pointers:
+**
+** *pOp is set to one of [SQLITE_INSERT], [SQLITE_DELETE] or [SQLITE_UPDATE],
+** depending on the type of change that the iterator currently points to;
+**
+** *pnCol is set to the number of columns in the table affected by the change; and
+**
+** *pzTab is set to point to a nul-terminated utf-8 encoded string containing
+** the name of the table affected by the current change. The buffer remains
+** valid until either sqlcipher_sqlite3changeset_next() is called on the iterator
+** or until the conflict-handler function returns.
+**
+** If pbIndirect is not NULL, then *pbIndirect is set to true (1) if the change
** is an indirect change, or false (0) otherwise. See the documentation for
** [sqlcipher_sqlite3session_indirect()] for a description of direct and indirect
-** changes. Finally, if pOp is not NULL, then *pOp is set to one of
-** [SQLITE_INSERT], [SQLITE_DELETE] or [SQLITE_UPDATE], depending on the
-** type of change that the iterator currently points to.
+** changes.
**
** If no error occurs, SQLITE_OK is returned. If an error does occur, an
** SQLite error code is returned. The values of the output variables may not
@@ -13341,11 +13206,16 @@ struct fts5_api {
/************** Continuing where we left off in sqliteInt.h ******************/
/*
+** Reuse the STATIC_LRU for mutex access to sqlcipher_sqlite3_temp_directory.
+*/
+#define SQLITE_MUTEX_STATIC_TEMPDIR SQLITE_MUTEX_STATIC_VFS1
+
+/*
** Include the configuration header output by 'configure' if we're using the
** autoconf-based build
*/
#if defined(_HAVE_SQLITE_CONFIG_H) && !defined(SQLITECONFIG_H)
-/* #include "config.h" */
+#include "config.h"
#define SQLITECONFIG_H 1
#endif
@@ -13582,9 +13452,11 @@ struct fts5_api {
# define __has_extension(x) 0 /* compatibility with non-clang compilers */
#endif
#if GCC_VERSION>=4007000 || __has_extension(c_atomic)
+# define SQLITE_ATOMIC_INTRINSICS 1
# define AtomicLoad(PTR) __atomic_load_n((PTR),__ATOMIC_RELAXED)
# define AtomicStore(PTR,VAL) __atomic_store_n((PTR),(VAL),__ATOMIC_RELAXED)
#else
+# define SQLITE_ATOMIC_INTRINSICS 0
# define AtomicLoad(PTR) (*(PTR))
# define AtomicStore(PTR,VAL) (*(PTR) = (VAL))
#endif
@@ -13789,11 +13661,12 @@ struct fts5_api {
** 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 sqlcipher_sqlite3Coverage(int);
-# define testcase(X) if( X ){ sqlcipher_sqlite3Coverage(__LINE__); }
+#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_DEBUG)
+# ifndef SQLITE_AMALGAMATION
+ extern unsigned int sqlcipher_sqlite3CoverageCounter;
+# endif
+# define testcase(X) if( X ){ sqlcipher_sqlite3CoverageCounter += (unsigned)__LINE__; }
#else
# define testcase(X)
#endif
@@ -13824,6 +13697,14 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Coverage(int);
#endif
/*
+** Disable ALWAYS() and NEVER() (make them pass-throughs) for coverage
+** and mutation testing
+*/
+#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
+# define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1
+#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
@@ -13838,7 +13719,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Coverage(int);
** be true and false so that the unreachable code they specify will
** not be counted as untested code.
*/
-#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
+#if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS)
# define ALWAYS(X) (1)
# define NEVER(X) (0)
#elif !defined(NDEBUG)
@@ -13850,26 +13731,6 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Coverage(int);
#endif
/*
-** The harmless(X) macro indicates that expression X is usually false
-** but can be true without causing any problems, but we don't know of
-** any way to cause X to be true.
-**
-** In debugging and testing builds, this macro will abort if X is ever
-** true. In this way, developers are alerted to a possible test case
-** that causes X to be true. If a harmless macro ever fails, that is
-** an opportunity to change the macro into a testcase() and add a new
-** test case to the test suite.
-**
-** For normal production builds, harmless(X) is a no-op, since it does
-** not matter whether expression X is true or false.
-*/
-#ifdef SQLITE_DEBUG
-# define harmless(X) assert(!(X));
-#else
-# define harmless(X)
-#endif
-
-/*
** Some conditionals are optimizations only. In other words, if the
** conditionals are replaced with a constant 1 (true) or 0 (false) then
** the correct answer is still obtained, though perhaps not as quickly.
@@ -13933,6 +13794,13 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Coverage(int);
#endif
/*
+** SQLITE_OMIT_VIRTUALTABLE implies SQLITE_OMIT_ALTERTABLE
+*/
+#if defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_ALTERTABLE)
+# define SQLITE_OMIT_ALTERTABLE
+#endif
+
+/*
** Return true (non-zero) if the input is an 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.
@@ -14044,7 +13912,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3HashClear(Hash*);
/*
** Number of entries in a hash table
*/
-/* #define sqliteHashCount(H) ((H)->count) // NOT USED */
+#define sqliteHashCount(H) ((H)->count)
#endif /* SQLITE_HASH_H */
@@ -14076,8 +13944,8 @@ SQLITE_PRIVATE void sqlcipher_sqlite3HashClear(Hash*);
#define TK_LP 22
#define TK_RP 23
#define TK_AS 24
-#define TK_WITHOUT 25
-#define TK_COMMA 26
+#define TK_COMMA 25
+#define TK_WITHOUT 26
#define TK_ABORT 27
#define TK_ACTION 28
#define TK_AFTER 29
@@ -14148,90 +14016,94 @@ SQLITE_PRIVATE void sqlcipher_sqlite3HashClear(Hash*);
#define TK_TIES 94
#define TK_GENERATED 95
#define TK_ALWAYS 96
-#define TK_REINDEX 97
-#define TK_RENAME 98
-#define TK_CTIME_KW 99
-#define TK_ANY 100
-#define TK_BITAND 101
-#define TK_BITOR 102
-#define TK_LSHIFT 103
-#define TK_RSHIFT 104
-#define TK_PLUS 105
-#define TK_MINUS 106
-#define TK_STAR 107
-#define TK_SLASH 108
-#define TK_REM 109
-#define TK_CONCAT 110
-#define TK_COLLATE 111
-#define TK_BITNOT 112
-#define TK_ON 113
-#define TK_INDEXED 114
-#define TK_STRING 115
-#define TK_JOIN_KW 116
-#define TK_CONSTRAINT 117
-#define TK_DEFAULT 118
-#define TK_NULL 119
-#define TK_PRIMARY 120
-#define TK_UNIQUE 121
-#define TK_CHECK 122
-#define TK_REFERENCES 123
-#define TK_AUTOINCR 124
-#define TK_INSERT 125
-#define TK_DELETE 126
-#define TK_UPDATE 127
-#define TK_SET 128
-#define TK_DEFERRABLE 129
-#define TK_FOREIGN 130
-#define TK_DROP 131
-#define TK_UNION 132
-#define TK_ALL 133
-#define TK_EXCEPT 134
-#define TK_INTERSECT 135
-#define TK_SELECT 136
-#define TK_VALUES 137
-#define TK_DISTINCT 138
-#define TK_DOT 139
-#define TK_FROM 140
-#define TK_JOIN 141
-#define TK_USING 142
-#define TK_ORDER 143
-#define TK_GROUP 144
-#define TK_HAVING 145
-#define TK_LIMIT 146
-#define TK_WHERE 147
-#define TK_INTO 148
-#define TK_NOTHING 149
-#define TK_FLOAT 150
-#define TK_BLOB 151
-#define TK_INTEGER 152
-#define TK_VARIABLE 153
-#define TK_CASE 154
-#define TK_WHEN 155
-#define TK_THEN 156
-#define TK_ELSE 157
-#define TK_INDEX 158
-#define TK_ALTER 159
-#define TK_ADD 160
-#define TK_WINDOW 161
-#define TK_OVER 162
-#define TK_FILTER 163
-#define TK_COLUMN 164
-#define TK_AGG_FUNCTION 165
-#define TK_AGG_COLUMN 166
-#define TK_TRUEFALSE 167
-#define TK_ISNOT 168
-#define TK_FUNCTION 169
-#define TK_UMINUS 170
-#define TK_UPLUS 171
-#define TK_TRUTH 172
-#define TK_REGISTER 173
-#define TK_VECTOR 174
-#define TK_SELECT_COLUMN 175
-#define TK_IF_NULL_ROW 176
-#define TK_ASTERISK 177
-#define TK_SPAN 178
-#define TK_SPACE 179
-#define TK_ILLEGAL 180
+#define TK_MATERIALIZED 97
+#define TK_REINDEX 98
+#define TK_RENAME 99
+#define TK_CTIME_KW 100
+#define TK_ANY 101
+#define TK_BITAND 102
+#define TK_BITOR 103
+#define TK_LSHIFT 104
+#define TK_RSHIFT 105
+#define TK_PLUS 106
+#define TK_MINUS 107
+#define TK_STAR 108
+#define TK_SLASH 109
+#define TK_REM 110
+#define TK_CONCAT 111
+#define TK_PTR 112
+#define TK_COLLATE 113
+#define TK_BITNOT 114
+#define TK_ON 115
+#define TK_INDEXED 116
+#define TK_STRING 117
+#define TK_JOIN_KW 118
+#define TK_CONSTRAINT 119
+#define TK_DEFAULT 120
+#define TK_NULL 121
+#define TK_PRIMARY 122
+#define TK_UNIQUE 123
+#define TK_CHECK 124
+#define TK_REFERENCES 125
+#define TK_AUTOINCR 126
+#define TK_INSERT 127
+#define TK_DELETE 128
+#define TK_UPDATE 129
+#define TK_SET 130
+#define TK_DEFERRABLE 131
+#define TK_FOREIGN 132
+#define TK_DROP 133
+#define TK_UNION 134
+#define TK_ALL 135
+#define TK_EXCEPT 136
+#define TK_INTERSECT 137
+#define TK_SELECT 138
+#define TK_VALUES 139
+#define TK_DISTINCT 140
+#define TK_DOT 141
+#define TK_FROM 142
+#define TK_JOIN 143
+#define TK_USING 144
+#define TK_ORDER 145
+#define TK_GROUP 146
+#define TK_HAVING 147
+#define TK_LIMIT 148
+#define TK_WHERE 149
+#define TK_RETURNING 150
+#define TK_INTO 151
+#define TK_NOTHING 152
+#define TK_FLOAT 153
+#define TK_BLOB 154
+#define TK_INTEGER 155
+#define TK_VARIABLE 156
+#define TK_CASE 157
+#define TK_WHEN 158
+#define TK_THEN 159
+#define TK_ELSE 160
+#define TK_INDEX 161
+#define TK_ALTER 162
+#define TK_ADD 163
+#define TK_WINDOW 164
+#define TK_OVER 165
+#define TK_FILTER 166
+#define TK_COLUMN 167
+#define TK_AGG_FUNCTION 168
+#define TK_AGG_COLUMN 169
+#define TK_TRUEFALSE 170
+#define TK_ISNOT 171
+#define TK_FUNCTION 172
+#define TK_UMINUS 173
+#define TK_UPLUS 174
+#define TK_TRUTH 175
+#define TK_REGISTER 176
+#define TK_VECTOR 177
+#define TK_SELECT_COLUMN 178
+#define TK_IF_NULL_ROW 179
+#define TK_ASTERISK 180
+#define TK_SPAN 181
+#define TK_ERROR 182
+#define TK_SPACE 183
+#define TK_ILLEGAL 184
/************** End of parse.h ***********************************************/
/************** Continuing where we left off in sqliteInt.h ******************/
@@ -14337,7 +14209,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3HashClear(Hash*);
** number of pages. A negative number N translations means that a buffer
** of -1024*N bytes is allocated and used for as many pages as it will hold.
**
-** The default value of "20" was choosen to minimize the run-time of the
+** The default value of "20" was chosen to minimize the run-time of the
** speedtest1 test program with options: --shrink-memory --reprepare
*/
#ifndef SQLITE_DEFAULT_PCACHE_INITSZ
@@ -14499,6 +14371,7 @@ typedef INT16_TYPE LogEst;
# define SQLITE_PTRSIZE __SIZEOF_POINTER__
# elif defined(i386) || defined(__i386__) || defined(_M_IX86) || \
defined(_M_ARM) || defined(__arm__) || defined(__x86) || \
+ (defined(__APPLE__) && defined(__POWERPC__)) || \
(defined(__TOS_AIX__) && !defined(__64BIT__))
# define SQLITE_PTRSIZE 4
# else
@@ -14580,8 +14453,19 @@ typedef INT16_TYPE LogEst;
/*
** Round up a number to the next larger multiple of 8. This is used
** to force 8-byte alignment on 64-bit architectures.
+**
+** ROUND8() always does the rounding, for any argument.
+**
+** ROUND8P() assumes that the argument is already an integer number of
+** pointers in size, and so it is a no-op on systems where the pointer
+** size is 8.
*/
#define ROUND8(x) (((x)+7)&~7)
+#if SQLITE_PTRSIZE==8
+# define ROUND8P(x) (x)
+#else
+# define ROUND8P(x) (((x)+7)&~7)
+#endif
/*
** Round down to the nearest multiple of 8
@@ -14644,25 +14528,38 @@ typedef INT16_TYPE LogEst;
#endif
/*
-** SELECTTRACE_ENABLED will be either 1 or 0 depending on whether or not
-** the Select query generator tracing logic is turned on.
+** TREETRACE_ENABLED will be either 1 or 0 depending on whether or not
+** the Abstract Syntax Tree tracing logic is turned on.
*/
-#if defined(SQLITE_ENABLE_SELECTTRACE)
-# define SELECTTRACE_ENABLED 1
-#else
-# define SELECTTRACE_ENABLED 0
+#if !defined(SQLITE_AMALGAMATION)
+SQLITE_PRIVATE u32 sqlcipher_sqlite3TreeTrace;
#endif
-#if defined(SQLITE_ENABLE_SELECTTRACE)
-# define SELECTTRACE_ENABLED 1
+#if defined(SQLITE_DEBUG) \
+ && (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_SELECTTRACE) \
+ || defined(SQLITE_ENABLE_TREETRACE))
+# define TREETRACE_ENABLED 1
# define SELECTTRACE(K,P,S,X) \
- if(sqlcipher_sqlite3_unsupported_selecttrace&(K)) \
+ if(sqlcipher_sqlite3TreeTrace&(K)) \
sqlcipher_sqlite3DebugPrintf("%u/%d/%p: ",(S)->selId,(P)->addrExplain,(S)),\
sqlcipher_sqlite3DebugPrintf X
#else
# define SELECTTRACE(K,P,S,X)
-# define SELECTTRACE_ENABLED 0
+# define TREETRACE_ENABLED 0
+#endif
+
+/*
+** Macros for "wheretrace"
+*/
+SQLITE_PRIVATE u32 sqlcipher_sqlite3WhereTrace;
+#if defined(SQLITE_DEBUG) \
+ && (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHERETRACE))
+# define WHERETRACE(K,X) if(sqlcipher_sqlite3WhereTrace&(K)) sqlcipher_sqlite3DebugPrintf X
+# define WHERETRACE_ENABLED 1
+#else
+# define WHERETRACE(K,X)
#endif
+
/*
** An instance of the following structure is used to store the busy-handler
** callback for a given sqlite handle.
@@ -14681,11 +14578,25 @@ struct BusyHandler {
/*
** Name of table that holds the database schema.
+**
+** The PREFERRED names are used whereever possible. But LEGACY is also
+** used for backwards compatibility.
+**
+** 1. Queries can use either the PREFERRED or the LEGACY names
+** 2. The sqlcipher_sqlite3_set_authorizer() callback uses the LEGACY name
+** 3. The PRAGMA table_list statement uses the PREFERRED name
+**
+** The LEGACY names are stored in the internal symbol hash table
+** in support of (2). Names are translated using sqlcipher_sqlite3PreferredTableName()
+** for (3). The sqlcipher_sqlite3FindTable() function takes care of translating
+** names for (1).
+**
+** Note that "sqlite_temp_schema" can also be called "temp.sqlite_schema".
*/
-#define DFLT_SCHEMA_TABLE "sqlite_master"
-#define DFLT_TEMP_SCHEMA_TABLE "sqlite_temp_master"
-#define ALT_SCHEMA_TABLE "sqlite_schema"
-#define ALT_TEMP_SCHEMA_TABLE "sqlite_temp_schema"
+#define LEGACY_SCHEMA_TABLE "sqlite_master"
+#define LEGACY_TEMP_SCHEMA_TABLE "sqlite_temp_master"
+#define PREFERRED_SCHEMA_TABLE "sqlite_schema"
+#define PREFERRED_TEMP_SCHEMA_TABLE "sqlite_temp_schema"
/*
@@ -14697,7 +14608,7 @@ struct BusyHandler {
** The name of the schema table. The name is different for TEMP.
*/
#define SCHEMA_TABLE(x) \
- ((!OMIT_TEMPDB)&&(x==1)?DFLT_TEMP_SCHEMA_TABLE:DFLT_SCHEMA_TABLE)
+ ((!OMIT_TEMPDB)&&(x==1)?LEGACY_TEMP_SCHEMA_TABLE:LEGACY_SCHEMA_TABLE)
/*
** A convenience macro that returns the number of elements in
@@ -14718,7 +14629,7 @@ struct BusyHandler {
** pointer will work here as long as it is distinct from SQLITE_STATIC
** and SQLITE_TRANSIENT.
*/
-#define SQLITE_DYNAMIC ((sqlcipher_sqlite3_destructor_type)sqlcipher_sqlite3OomFault)
+#define SQLITE_DYNAMIC ((sqlcipher_sqlite3_destructor_type)sqlcipher_sqlite3OomClear)
/*
** When SQLITE_OMIT_WSD is defined, it means that the target platform does
@@ -14774,7 +14685,10 @@ typedef struct AutoincInfo AutoincInfo;
typedef struct Bitvec Bitvec;
typedef struct CollSeq CollSeq;
typedef struct Column Column;
+typedef struct Cte Cte;
+typedef struct CteUse CteUse;
typedef struct Db Db;
+typedef struct DbFixer DbFixer;
typedef struct Schema Schema;
typedef struct Expr Expr;
typedef struct ExprList ExprList;
@@ -14791,15 +14705,19 @@ typedef struct Lookaside Lookaside;
typedef struct LookasideSlot LookasideSlot;
typedef struct Module Module;
typedef struct NameContext NameContext;
+typedef struct OnOrUsing OnOrUsing;
typedef struct Parse Parse;
+typedef struct ParseCleanup ParseCleanup;
typedef struct PreUpdate PreUpdate;
typedef struct PrintfArguments PrintfArguments;
typedef struct RenameToken RenameToken;
+typedef struct Returning Returning;
typedef struct RowSet RowSet;
typedef struct Savepoint Savepoint;
typedef struct Select Select;
typedef struct SQLiteThread SQLiteThread;
typedef struct SelectDest SelectDest;
+typedef struct SrcItem SrcItem;
typedef struct SrcList SrcList;
typedef struct sqlcipher_sqlite3_str StrAccum; /* Internal alias for sqlcipher_sqlite3_str */
typedef struct Table Table;
@@ -14840,10 +14758,11 @@ typedef struct With With;
/*
** A bit in a Bitmask
*/
-#define MASKBIT(n) (((Bitmask)1)<<(n))
-#define MASKBIT64(n) (((u64)1)<<(n))
-#define MASKBIT32(n) (((unsigned int)1)<<(n))
-#define ALLBITS ((Bitmask)-1)
+#define MASKBIT(n) (((Bitmask)1)<<(n))
+#define MASKBIT64(n) (((u64)1)<<(n))
+#define MASKBIT32(n) (((unsigned int)1)<<(n))
+#define SMASKBIT32(n) ((n)<=31?((unsigned int)1)<<(n):0)
+#define ALLBITS ((Bitmask)-1)
/* A VList object records a mapping between parameters/variables/wildcards
** in the SQL statement (such as $abc, @pqr, or :xyz) and the integer
@@ -14905,14 +14824,15 @@ typedef struct Pager Pager;
typedef struct PgHdr DbPage;
/*
-** Page number PAGER_MJ_PGNO is never used in an SQLite database (it is
+** Page number PAGER_SJ_PGNO is never used in an SQLite database (it is
** reserved for working around a windows/posix incompatibility). It is
** used in the journal to signify that the remainder of the journal file
** is devoted to storing a super-journal name - there are no more pages to
** roll back. See comments for function writeSuperJournal() in pager.c
** for details.
*/
-#define PAGER_MJ_PGNO(x) ((Pgno)((PENDING_BYTE/((x)->pageSize))+1))
+#define PAGER_SJ_PGNO_COMPUTED(x) ((Pgno)((PENDING_BYTE/((x)->pageSize))+1))
+#define PAGER_SJ_PGNO(x) ((x)->lckPgno)
/*
** Allowed values for the flags parameter to sqlcipher_sqlite3PagerOpen().
@@ -15093,7 +15013,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3PagerRekey(DbPage*, Pgno, u16);
/* BEGIN SQLCIPHER */
#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_WAL)
-SQLITE_PRIVATE void *sqlcipher_sqlite3PagerCodec(DbPage *);
+void *sqlcipherPagerCodec(DbPage *);
#endif
/* END SQLCIPHER */
@@ -15243,7 +15163,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3BtreeIncrVacuum(Btree *);
#define BTREE_BLOBKEY 2 /* Table has keys only - no data */
SQLITE_PRIVATE int sqlcipher_sqlite3BtreeDropTable(Btree*, int, int*);
-SQLITE_PRIVATE int sqlcipher_sqlite3BtreeClearTable(Btree*, int, int*);
+SQLITE_PRIVATE int sqlcipher_sqlite3BtreeClearTable(Btree*, int, i64*);
SQLITE_PRIVATE int sqlcipher_sqlite3BtreeClearTableOfCursor(BtCursor*);
SQLITE_PRIVATE int sqlcipher_sqlite3BtreeTripAllCursors(Btree*, int, int);
@@ -15367,13 +15287,17 @@ SQLITE_PRIVATE void sqlcipher_sqlite3BtreeCursorHint(BtCursor*, int, ...);
#endif
SQLITE_PRIVATE int sqlcipher_sqlite3BtreeCloseCursor(BtCursor*);
-SQLITE_PRIVATE int sqlcipher_sqlite3BtreeMovetoUnpacked(
+SQLITE_PRIVATE int sqlcipher_sqlite3BtreeTableMoveto(
BtCursor*,
- UnpackedRecord *pUnKey,
i64 intKey,
int bias,
int *pRes
);
+SQLITE_PRIVATE int sqlcipher_sqlite3BtreeIndexMoveto(
+ BtCursor*,
+ UnpackedRecord *pUnKey,
+ int *pRes
+);
SQLITE_PRIVATE int sqlcipher_sqlite3BtreeCursorHasMoved(BtCursor*);
SQLITE_PRIVATE int sqlcipher_sqlite3BtreeCursorRestore(BtCursor*, int*);
SQLITE_PRIVATE int sqlcipher_sqlite3BtreeDelete(BtCursor*, u8 flags);
@@ -15382,6 +15306,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3BtreeDelete(BtCursor*, u8 flags);
#define BTREE_SAVEPOSITION 0x02 /* Leave cursor pointing at NEXT or PREV */
#define BTREE_AUXDELETE 0x04 /* not the primary delete operation */
#define BTREE_APPEND 0x08 /* Insert is likely an append */
+#define BTREE_PREFORMAT 0x80 /* Inserted data is a preformated cell */
/* An instance of the BtreePayload object describes the content of a single
** entry in either an index or table btree.
@@ -15481,6 +15406,8 @@ SQLITE_PRIVATE void sqlcipher_sqlite3BtreeCursorList(Btree*);
SQLITE_PRIVATE int sqlcipher_sqlite3BtreeCheckpoint(Btree*, int, int *, int *);
#endif
+SQLITE_PRIVATE int sqlcipher_sqlite3BtreeTransferRow(BtCursor*, BtCursor*, i64);
+
/*
** If we are not using shared cache, then there is no need to
** use mutexes to access the BtShared structures. So make the
@@ -15593,7 +15520,6 @@ struct VdbeOp {
#ifdef SQLITE_ENABLE_CURSOR_HINTS
Expr *pExpr; /* Used when p4type is P4_EXPR */
#endif
- int (*xAdvance)(BtCursor *, int);
} p4;
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
char *zComment; /* Comment to improve readability */
@@ -15644,21 +15570,19 @@ typedef struct VdbeOpList VdbeOpList;
#define P4_COLLSEQ (-2) /* P4 is a pointer to a CollSeq structure */
#define P4_INT32 (-3) /* P4 is a 32-bit signed integer */
#define P4_SUBPROGRAM (-4) /* P4 is a pointer to a SubProgram structure */
-#define P4_ADVANCE (-5) /* P4 is a pointer to BtreeNext() or BtreePrev() */
-#define P4_TABLE (-6) /* P4 is a pointer to a Table structure */
+#define P4_TABLE (-5) /* P4 is a pointer to a Table structure */
/* Above do not own any resources. Must free those below */
-#define P4_FREE_IF_LE (-7)
-#define P4_DYNAMIC (-7) /* Pointer to memory from sqliteMalloc() */
-#define P4_FUNCDEF (-8) /* P4 is a pointer to a FuncDef structure */
-#define P4_KEYINFO (-9) /* P4 is a pointer to a KeyInfo structure */
-#define P4_EXPR (-10) /* P4 is a pointer to an Expr tree */
-#define P4_MEM (-11) /* P4 is a pointer to a Mem* structure */
-#define P4_VTAB (-12) /* P4 is a pointer to an sqlcipher_sqlite3_vtab structure */
-#define P4_REAL (-13) /* P4 is a 64-bit floating point value */
-#define P4_INT64 (-14) /* P4 is a 64-bit signed integer */
-#define P4_INTARRAY (-15) /* P4 is a vector of 32-bit integers */
-#define P4_FUNCCTX (-16) /* P4 is a pointer to an sqlcipher_sqlite3_context object */
-#define P4_DYNBLOB (-17) /* Pointer to memory from sqliteMalloc() */
+#define P4_FREE_IF_LE (-6)
+#define P4_DYNAMIC (-6) /* Pointer to memory from sqliteMalloc() */
+#define P4_FUNCDEF (-7) /* P4 is a pointer to a FuncDef structure */
+#define P4_KEYINFO (-8) /* P4 is a pointer to a KeyInfo structure */
+#define P4_EXPR (-9) /* P4 is a pointer to an Expr tree */
+#define P4_MEM (-10) /* P4 is a pointer to a Mem* structure */
+#define P4_VTAB (-11) /* P4 is a pointer to an sqlcipher_sqlite3_vtab structure */
+#define P4_REAL (-12) /* P4 is a 64-bit floating point value */
+#define P4_INT64 (-13) /* P4 is a 64-bit signed integer */
+#define P4_INTARRAY (-14) /* P4 is a vector of 32-bit integers */
+#define P4_FUNCCTX (-15) /* P4 is a pointer to an sqlcipher_sqlite3_context object */
/* Error message codes for OP_Halt */
#define P5_ConstraintNotNull 1
@@ -15703,53 +15627,53 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_Savepoint 0
#define OP_AutoCommit 1
#define OP_Transaction 2
-#define OP_SorterNext 3 /* jump */
-#define OP_Prev 4 /* jump */
-#define OP_Next 5 /* jump */
-#define OP_Checkpoint 6
-#define OP_JournalMode 7
-#define OP_Vacuum 8
-#define OP_VFilter 9 /* jump, synopsis: iplan=r[P3] zplan='P4' */
-#define OP_VUpdate 10 /* synopsis: data=r[P3@P2] */
-#define OP_Goto 11 /* jump */
-#define OP_Gosub 12 /* jump */
-#define OP_InitCoroutine 13 /* jump */
-#define OP_Yield 14 /* jump */
-#define OP_MustBeInt 15 /* jump */
-#define OP_Jump 16 /* jump */
-#define OP_Once 17 /* jump */
-#define OP_If 18 /* jump */
+#define OP_Checkpoint 3
+#define OP_JournalMode 4
+#define OP_Vacuum 5
+#define OP_VFilter 6 /* jump, synopsis: iplan=r[P3] zplan='P4' */
+#define OP_VUpdate 7 /* synopsis: data=r[P3@P2] */
+#define OP_Goto 8 /* jump */
+#define OP_Gosub 9 /* jump */
+#define OP_InitCoroutine 10 /* jump */
+#define OP_Yield 11 /* jump */
+#define OP_MustBeInt 12 /* jump */
+#define OP_Jump 13 /* jump */
+#define OP_Once 14 /* jump */
+#define OP_If 15 /* jump */
+#define OP_IfNot 16 /* jump */
+#define OP_IsNullOrType 17 /* jump, synopsis: if typeof(r[P1]) IN (P3,5) goto P2 */
+#define OP_IfNullRow 18 /* jump, synopsis: if P1.nullRow then r[P3]=NULL, goto P2 */
#define OP_Not 19 /* same as TK_NOT, synopsis: r[P2]= !r[P1] */
-#define OP_IfNot 20 /* jump */
-#define OP_IfNullRow 21 /* jump, synopsis: if P1.nullRow then r[P3]=NULL, goto P2 */
-#define OP_SeekLT 22 /* jump, synopsis: key=r[P3@P4] */
-#define OP_SeekLE 23 /* jump, synopsis: key=r[P3@P4] */
-#define OP_SeekGE 24 /* jump, synopsis: key=r[P3@P4] */
-#define OP_SeekGT 25 /* jump, synopsis: key=r[P3@P4] */
-#define OP_IfNotOpen 26 /* jump, synopsis: if( !csr[P1] ) goto P2 */
-#define OP_IfNoHope 27 /* jump, synopsis: key=r[P3@P4] */
-#define OP_NoConflict 28 /* jump, synopsis: key=r[P3@P4] */
-#define OP_NotFound 29 /* jump, synopsis: key=r[P3@P4] */
-#define OP_Found 30 /* jump, synopsis: key=r[P3@P4] */
-#define OP_SeekRowid 31 /* jump, synopsis: intkey=r[P3] */
-#define OP_NotExists 32 /* jump, synopsis: intkey=r[P3] */
-#define OP_Last 33 /* jump */
-#define OP_IfSmaller 34 /* jump */
-#define OP_SorterSort 35 /* jump */
-#define OP_Sort 36 /* jump */
-#define OP_Rewind 37 /* jump */
-#define OP_IdxLE 38 /* jump, synopsis: key=r[P3@P4] */
-#define OP_IdxGT 39 /* jump, synopsis: key=r[P3@P4] */
-#define OP_IdxLT 40 /* jump, synopsis: key=r[P3@P4] */
-#define OP_IdxGE 41 /* jump, synopsis: key=r[P3@P4] */
-#define OP_RowSetRead 42 /* jump, synopsis: r[P3]=rowset(P1) */
+#define OP_SeekLT 20 /* jump, synopsis: key=r[P3@P4] */
+#define OP_SeekLE 21 /* jump, synopsis: key=r[P3@P4] */
+#define OP_SeekGE 22 /* jump, synopsis: key=r[P3@P4] */
+#define OP_SeekGT 23 /* jump, synopsis: key=r[P3@P4] */
+#define OP_IfNotOpen 24 /* jump, synopsis: if( !csr[P1] ) goto P2 */
+#define OP_IfNoHope 25 /* jump, synopsis: key=r[P3@P4] */
+#define OP_NoConflict 26 /* jump, synopsis: key=r[P3@P4] */
+#define OP_NotFound 27 /* jump, synopsis: key=r[P3@P4] */
+#define OP_Found 28 /* jump, synopsis: key=r[P3@P4] */
+#define OP_SeekRowid 29 /* jump, synopsis: intkey=r[P3] */
+#define OP_NotExists 30 /* jump, synopsis: intkey=r[P3] */
+#define OP_Last 31 /* jump */
+#define OP_IfSmaller 32 /* jump */
+#define OP_SorterSort 33 /* jump */
+#define OP_Sort 34 /* jump */
+#define OP_Rewind 35 /* jump */
+#define OP_SorterNext 36 /* jump */
+#define OP_Prev 37 /* jump */
+#define OP_Next 38 /* jump */
+#define OP_IdxLE 39 /* jump, synopsis: key=r[P3@P4] */
+#define OP_IdxGT 40 /* jump, synopsis: key=r[P3@P4] */
+#define OP_IdxLT 41 /* jump, synopsis: key=r[P3@P4] */
+#define OP_IdxGE 42 /* jump, synopsis: key=r[P3@P4] */
#define OP_Or 43 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */
#define OP_And 44 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */
-#define OP_RowSetTest 45 /* jump, synopsis: if r[P3] in rowset(P1) goto P2 */
-#define OP_Program 46 /* jump */
-#define OP_FkIfZero 47 /* jump, synopsis: if fkctr[P1]==0 goto P2 */
-#define OP_IfPos 48 /* jump, synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */
-#define OP_IfNotZero 49 /* jump, synopsis: if r[P1]!=0 then r[P1]--, goto P2 */
+#define OP_RowSetRead 45 /* jump, synopsis: r[P3]=rowset(P1) */
+#define OP_RowSetTest 46 /* jump, synopsis: if r[P3] in rowset(P1) goto P2 */
+#define OP_Program 47 /* jump */
+#define OP_FkIfZero 48 /* jump, synopsis: if fkctr[P1]==0 goto P2 */
+#define OP_IfPos 49 /* jump, synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */
#define OP_IsNull 50 /* jump, same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */
#define OP_NotNull 51 /* jump, same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */
#define OP_Ne 52 /* jump, same as TK_NE, synopsis: IF r[P3]!=r[P1] */
@@ -15758,125 +15682,135 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_Le 55 /* jump, same as TK_LE, synopsis: IF r[P3]<=r[P1] */
#define OP_Lt 56 /* jump, same as TK_LT, synopsis: IF r[P3]<r[P1] */
#define OP_Ge 57 /* jump, same as TK_GE, synopsis: IF r[P3]>=r[P1] */
-#define OP_ElseNotEq 58 /* jump, same as TK_ESCAPE */
-#define OP_DecrJumpZero 59 /* jump, synopsis: if (--r[P1])==0 goto P2 */
-#define OP_IncrVacuum 60 /* jump */
-#define OP_VNext 61 /* jump */
-#define OP_Init 62 /* jump, synopsis: Start at P2 */
-#define OP_PureFunc 63 /* synopsis: r[P3]=func(r[P2@NP]) */
-#define OP_Function 64 /* synopsis: r[P3]=func(r[P2@NP]) */
-#define OP_Return 65
-#define OP_EndCoroutine 66
-#define OP_HaltIfNull 67 /* synopsis: if r[P3]=null halt */
-#define OP_Halt 68
-#define OP_Integer 69 /* synopsis: r[P2]=P1 */
-#define OP_Int64 70 /* synopsis: r[P2]=P4 */
-#define OP_String 71 /* synopsis: r[P2]='P4' (len=P1) */
-#define OP_Null 72 /* synopsis: r[P2..P3]=NULL */
-#define OP_SoftNull 73 /* synopsis: r[P1]=NULL */
-#define OP_Blob 74 /* synopsis: r[P2]=P4 (len=P1) */
-#define OP_Variable 75 /* synopsis: r[P2]=parameter(P1,P4) */
-#define OP_Move 76 /* synopsis: r[P2@P3]=r[P1@P3] */
-#define OP_Copy 77 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */
-#define OP_SCopy 78 /* synopsis: r[P2]=r[P1] */
-#define OP_IntCopy 79 /* synopsis: r[P2]=r[P1] */
-#define OP_ResultRow 80 /* synopsis: output=r[P1@P2] */
-#define OP_CollSeq 81
-#define OP_AddImm 82 /* synopsis: r[P1]=r[P1]+P2 */
-#define OP_RealAffinity 83
-#define OP_Cast 84 /* synopsis: affinity(r[P1]) */
-#define OP_Permutation 85
-#define OP_Compare 86 /* synopsis: r[P1@P3] <-> r[P2@P3] */
-#define OP_IsTrue 87 /* synopsis: r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4 */
-#define OP_Offset 88 /* synopsis: r[P3] = sqlite_offset(P1) */
-#define OP_Column 89 /* synopsis: r[P3]=PX */
-#define OP_Affinity 90 /* synopsis: affinity(r[P1@P2]) */
-#define OP_MakeRecord 91 /* synopsis: r[P3]=mkrec(r[P1@P2]) */
-#define OP_Count 92 /* synopsis: r[P2]=count() */
-#define OP_ReadCookie 93
-#define OP_SetCookie 94
-#define OP_ReopenIdx 95 /* synopsis: root=P2 iDb=P3 */
-#define OP_OpenRead 96 /* synopsis: root=P2 iDb=P3 */
-#define OP_OpenWrite 97 /* synopsis: root=P2 iDb=P3 */
-#define OP_OpenDup 98
-#define OP_OpenAutoindex 99 /* synopsis: nColumn=P2 */
-#define OP_OpenEphemeral 100 /* synopsis: nColumn=P2 */
-#define OP_BitAnd 101 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
-#define OP_BitOr 102 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
-#define OP_ShiftLeft 103 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<<r[P1] */
-#define OP_ShiftRight 104 /* same as TK_RSHIFT, synopsis: r[P3]=r[P2]>>r[P1] */
-#define OP_Add 105 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
-#define OP_Subtract 106 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
-#define OP_Multiply 107 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
-#define OP_Divide 108 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
-#define OP_Remainder 109 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
-#define OP_Concat 110 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
-#define OP_SorterOpen 111
-#define OP_BitNot 112 /* same as TK_BITNOT, synopsis: r[P2]= ~r[P1] */
-#define OP_SequenceTest 113 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */
-#define OP_OpenPseudo 114 /* synopsis: P3 columns in r[P2] */
-#define OP_String8 115 /* same as TK_STRING, synopsis: r[P2]='P4' */
-#define OP_Close 116
-#define OP_ColumnsUsed 117
-#define OP_SeekScan 118 /* synopsis: Scan-ahead up to P1 rows */
-#define OP_SeekHit 119 /* synopsis: set P2<=seekHit<=P3 */
-#define OP_Sequence 120 /* synopsis: r[P2]=cursor[P1].ctr++ */
-#define OP_NewRowid 121 /* synopsis: r[P2]=rowid */
-#define OP_Insert 122 /* synopsis: intkey=r[P3] data=r[P2] */
-#define OP_Delete 123
-#define OP_ResetCount 124
-#define OP_SorterCompare 125 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */
-#define OP_SorterData 126 /* synopsis: r[P2]=data */
-#define OP_RowData 127 /* synopsis: r[P2]=data */
-#define OP_Rowid 128 /* synopsis: r[P2]=rowid */
-#define OP_NullRow 129
-#define OP_SeekEnd 130
-#define OP_IdxInsert 131 /* synopsis: key=r[P2] */
-#define OP_SorterInsert 132 /* synopsis: key=r[P2] */
-#define OP_IdxDelete 133 /* synopsis: key=r[P2@P3] */
-#define OP_DeferredSeek 134 /* synopsis: Move P3 to P1.rowid if needed */
-#define OP_IdxRowid 135 /* synopsis: r[P2]=rowid */
-#define OP_FinishSeek 136
-#define OP_Destroy 137
-#define OP_Clear 138
-#define OP_ResetSorter 139
-#define OP_CreateBtree 140 /* synopsis: r[P2]=root iDb=P1 flags=P3 */
-#define OP_SqlExec 141
-#define OP_ParseSchema 142
-#define OP_LoadAnalysis 143
-#define OP_DropTable 144
-#define OP_DropIndex 145
-#define OP_DropTrigger 146
-#define OP_IntegrityCk 147
-#define OP_RowSetAdd 148 /* synopsis: rowset(P1)=r[P2] */
-#define OP_Param 149
-#define OP_Real 150 /* same as TK_FLOAT, synopsis: r[P2]=P4 */
-#define OP_FkCounter 151 /* synopsis: fkctr[P1]+=P2 */
-#define OP_MemMax 152 /* synopsis: r[P1]=max(r[P1],r[P2]) */
-#define OP_OffsetLimit 153 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */
-#define OP_AggInverse 154 /* synopsis: accum=r[P3] inverse(r[P2@P5]) */
-#define OP_AggStep 155 /* synopsis: accum=r[P3] step(r[P2@P5]) */
-#define OP_AggStep1 156 /* synopsis: accum=r[P3] step(r[P2@P5]) */
-#define OP_AggValue 157 /* synopsis: r[P3]=value N=P2 */
-#define OP_AggFinal 158 /* synopsis: accum=r[P1] N=P2 */
-#define OP_Expire 159
-#define OP_CursorLock 160
-#define OP_CursorUnlock 161
-#define OP_TableLock 162 /* synopsis: iDb=P1 root=P2 write=P3 */
-#define OP_VBegin 163
-#define OP_VCreate 164
-#define OP_VDestroy 165
-#define OP_VOpen 166
-#define OP_VColumn 167 /* synopsis: r[P3]=vcolumn(P2) */
-#define OP_VRename 168
-#define OP_Pagecount 169
-#define OP_MaxPgcnt 170
-#define OP_Trace 171
-#define OP_CursorHint 172
-#define OP_ReleaseReg 173 /* synopsis: release r[P1@P2] mask P3 */
-#define OP_Noop 174
-#define OP_Explain 175
-#define OP_Abortable 176
+#define OP_ElseEq 58 /* jump, same as TK_ESCAPE */
+#define OP_IfNotZero 59 /* jump, synopsis: if r[P1]!=0 then r[P1]--, goto P2 */
+#define OP_DecrJumpZero 60 /* jump, synopsis: if (--r[P1])==0 goto P2 */
+#define OP_IncrVacuum 61 /* jump */
+#define OP_VNext 62 /* jump */
+#define OP_Filter 63 /* jump, synopsis: if key(P3@P4) not in filter(P1) goto P2 */
+#define OP_Init 64 /* jump, synopsis: Start at P2 */
+#define OP_PureFunc 65 /* synopsis: r[P3]=func(r[P2@NP]) */
+#define OP_Function 66 /* synopsis: r[P3]=func(r[P2@NP]) */
+#define OP_Return 67
+#define OP_EndCoroutine 68
+#define OP_HaltIfNull 69 /* synopsis: if r[P3]=null halt */
+#define OP_Halt 70
+#define OP_Integer 71 /* synopsis: r[P2]=P1 */
+#define OP_Int64 72 /* synopsis: r[P2]=P4 */
+#define OP_String 73 /* synopsis: r[P2]='P4' (len=P1) */
+#define OP_BeginSubrtn 74 /* synopsis: r[P2]=NULL */
+#define OP_Null 75 /* synopsis: r[P2..P3]=NULL */
+#define OP_SoftNull 76 /* synopsis: r[P1]=NULL */
+#define OP_Blob 77 /* synopsis: r[P2]=P4 (len=P1) */
+#define OP_Variable 78 /* synopsis: r[P2]=parameter(P1,P4) */
+#define OP_Move 79 /* synopsis: r[P2@P3]=r[P1@P3] */
+#define OP_Copy 80 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */
+#define OP_SCopy 81 /* synopsis: r[P2]=r[P1] */
+#define OP_IntCopy 82 /* synopsis: r[P2]=r[P1] */
+#define OP_FkCheck 83
+#define OP_ResultRow 84 /* synopsis: output=r[P1@P2] */
+#define OP_CollSeq 85
+#define OP_AddImm 86 /* synopsis: r[P1]=r[P1]+P2 */
+#define OP_RealAffinity 87
+#define OP_Cast 88 /* synopsis: affinity(r[P1]) */
+#define OP_Permutation 89
+#define OP_Compare 90 /* synopsis: r[P1@P3] <-> r[P2@P3] */
+#define OP_IsTrue 91 /* synopsis: r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4 */
+#define OP_ZeroOrNull 92 /* synopsis: r[P2] = 0 OR NULL */
+#define OP_Offset 93 /* synopsis: r[P3] = sqlite_offset(P1) */
+#define OP_Column 94 /* synopsis: r[P3]=PX cursor P1 column P2 */
+#define OP_TypeCheck 95 /* synopsis: typecheck(r[P1@P2]) */
+#define OP_Affinity 96 /* synopsis: affinity(r[P1@P2]) */
+#define OP_MakeRecord 97 /* synopsis: r[P3]=mkrec(r[P1@P2]) */
+#define OP_Count 98 /* synopsis: r[P2]=count() */
+#define OP_ReadCookie 99
+#define OP_SetCookie 100
+#define OP_ReopenIdx 101 /* synopsis: root=P2 iDb=P3 */
+#define OP_BitAnd 102 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
+#define OP_BitOr 103 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
+#define OP_ShiftLeft 104 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<<r[P1] */
+#define OP_ShiftRight 105 /* same as TK_RSHIFT, synopsis: r[P3]=r[P2]>>r[P1] */
+#define OP_Add 106 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
+#define OP_Subtract 107 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
+#define OP_Multiply 108 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
+#define OP_Divide 109 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
+#define OP_Remainder 110 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
+#define OP_Concat 111 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
+#define OP_OpenRead 112 /* synopsis: root=P2 iDb=P3 */
+#define OP_OpenWrite 113 /* synopsis: root=P2 iDb=P3 */
+#define OP_BitNot 114 /* same as TK_BITNOT, synopsis: r[P2]= ~r[P1] */
+#define OP_OpenDup 115
+#define OP_OpenAutoindex 116 /* synopsis: nColumn=P2 */
+#define OP_String8 117 /* same as TK_STRING, synopsis: r[P2]='P4' */
+#define OP_OpenEphemeral 118 /* synopsis: nColumn=P2 */
+#define OP_SorterOpen 119
+#define OP_SequenceTest 120 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */
+#define OP_OpenPseudo 121 /* synopsis: P3 columns in r[P2] */
+#define OP_Close 122
+#define OP_ColumnsUsed 123
+#define OP_SeekScan 124 /* synopsis: Scan-ahead up to P1 rows */
+#define OP_SeekHit 125 /* synopsis: set P2<=seekHit<=P3 */
+#define OP_Sequence 126 /* synopsis: r[P2]=cursor[P1].ctr++ */
+#define OP_NewRowid 127 /* synopsis: r[P2]=rowid */
+#define OP_Insert 128 /* synopsis: intkey=r[P3] data=r[P2] */
+#define OP_RowCell 129
+#define OP_Delete 130
+#define OP_ResetCount 131
+#define OP_SorterCompare 132 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */
+#define OP_SorterData 133 /* synopsis: r[P2]=data */
+#define OP_RowData 134 /* synopsis: r[P2]=data */
+#define OP_Rowid 135 /* synopsis: r[P2]=PX rowid of P1 */
+#define OP_NullRow 136
+#define OP_SeekEnd 137
+#define OP_IdxInsert 138 /* synopsis: key=r[P2] */
+#define OP_SorterInsert 139 /* synopsis: key=r[P2] */
+#define OP_IdxDelete 140 /* synopsis: key=r[P2@P3] */
+#define OP_DeferredSeek 141 /* synopsis: Move P3 to P1.rowid if needed */
+#define OP_IdxRowid 142 /* synopsis: r[P2]=rowid */
+#define OP_FinishSeek 143
+#define OP_Destroy 144
+#define OP_Clear 145
+#define OP_ResetSorter 146
+#define OP_CreateBtree 147 /* synopsis: r[P2]=root iDb=P1 flags=P3 */
+#define OP_SqlExec 148
+#define OP_ParseSchema 149
+#define OP_LoadAnalysis 150
+#define OP_DropTable 151
+#define OP_DropIndex 152
+#define OP_Real 153 /* same as TK_FLOAT, synopsis: r[P2]=P4 */
+#define OP_DropTrigger 154
+#define OP_IntegrityCk 155
+#define OP_RowSetAdd 156 /* synopsis: rowset(P1)=r[P2] */
+#define OP_Param 157
+#define OP_FkCounter 158 /* synopsis: fkctr[P1]+=P2 */
+#define OP_MemMax 159 /* synopsis: r[P1]=max(r[P1],r[P2]) */
+#define OP_OffsetLimit 160 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */
+#define OP_AggInverse 161 /* synopsis: accum=r[P3] inverse(r[P2@P5]) */
+#define OP_AggStep 162 /* synopsis: accum=r[P3] step(r[P2@P5]) */
+#define OP_AggStep1 163 /* synopsis: accum=r[P3] step(r[P2@P5]) */
+#define OP_AggValue 164 /* synopsis: r[P3]=value N=P2 */
+#define OP_AggFinal 165 /* synopsis: accum=r[P1] N=P2 */
+#define OP_Expire 166
+#define OP_CursorLock 167
+#define OP_CursorUnlock 168
+#define OP_TableLock 169 /* synopsis: iDb=P1 root=P2 write=P3 */
+#define OP_VBegin 170
+#define OP_VCreate 171
+#define OP_VDestroy 172
+#define OP_VOpen 173
+#define OP_VInitIn 174 /* synopsis: r[P2]=ValueList(P1,P3) */
+#define OP_VColumn 175 /* synopsis: r[P3]=vcolumn(P2) */
+#define OP_VRename 176
+#define OP_Pagecount 177
+#define OP_MaxPgcnt 178
+#define OP_ClrSubtype 179 /* synopsis: r[P1].subtype = 0 */
+#define OP_FilterAdd 180 /* synopsis: filter(P1) += key(P3@P4) */
+#define OP_Trace 181
+#define OP_CursorHint 182
+#define OP_ReleaseReg 183 /* synopsis: release r[P1@P2] mask P3 */
+#define OP_Noop 184
+#define OP_Explain 185
+#define OP_Abortable 186
/* Properties such as "out2" or "jump" that are specified in
** comments following the "case" for each opcode in the vdbe.c
@@ -15889,37 +15823,38 @@ typedef struct VdbeOpList VdbeOpList;
#define OPFLG_OUT2 0x10 /* out2: P2 is an output */
#define OPFLG_OUT3 0x20 /* out3: P3 is an output */
#define OPFLG_INITIALIZER {\
-/* 0 */ 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x10,\
-/* 8 */ 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x03, 0x03,\
-/* 16 */ 0x01, 0x01, 0x03, 0x12, 0x03, 0x01, 0x09, 0x09,\
-/* 24 */ 0x09, 0x09, 0x01, 0x09, 0x09, 0x09, 0x09, 0x09,\
-/* 32 */ 0x09, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\
-/* 40 */ 0x01, 0x01, 0x23, 0x26, 0x26, 0x0b, 0x01, 0x01,\
-/* 48 */ 0x03, 0x03, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b,\
-/* 56 */ 0x0b, 0x0b, 0x01, 0x03, 0x01, 0x01, 0x01, 0x00,\
-/* 64 */ 0x00, 0x02, 0x02, 0x08, 0x00, 0x10, 0x10, 0x10,\
-/* 72 */ 0x10, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10,\
-/* 80 */ 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x12,\
-/* 88 */ 0x20, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\
-/* 96 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x26, 0x26,\
-/* 104 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x00,\
-/* 112 */ 0x12, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,\
-/* 120 */ 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 128 */ 0x10, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x10,\
-/* 136 */ 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,\
-/* 144 */ 0x00, 0x00, 0x00, 0x00, 0x06, 0x10, 0x10, 0x00,\
-/* 152 */ 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 160 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 168 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 176 */ 0x00,}
-
-/* The sqlcipher_sqlite3P2Values() routine is able to run faster if it knows
+/* 0 */ 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,\
+/* 8 */ 0x01, 0x01, 0x01, 0x03, 0x03, 0x01, 0x01, 0x03,\
+/* 16 */ 0x03, 0x03, 0x01, 0x12, 0x09, 0x09, 0x09, 0x09,\
+/* 24 */ 0x01, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x01,\
+/* 32 */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\
+/* 40 */ 0x01, 0x01, 0x01, 0x26, 0x26, 0x23, 0x0b, 0x01,\
+/* 48 */ 0x01, 0x03, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b,\
+/* 56 */ 0x0b, 0x0b, 0x01, 0x03, 0x03, 0x01, 0x01, 0x01,\
+/* 64 */ 0x01, 0x00, 0x00, 0x02, 0x02, 0x08, 0x00, 0x10,\
+/* 72 */ 0x10, 0x10, 0x00, 0x10, 0x00, 0x10, 0x10, 0x00,\
+/* 80 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x02, 0x02,\
+/* 88 */ 0x02, 0x00, 0x00, 0x12, 0x1e, 0x20, 0x00, 0x00,\
+/* 96 */ 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x26, 0x26,\
+/* 104 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,\
+/* 112 */ 0x00, 0x00, 0x12, 0x00, 0x00, 0x10, 0x00, 0x00,\
+/* 120 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10,\
+/* 128 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,\
+/* 136 */ 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x10, 0x00,\
+/* 144 */ 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,\
+/* 152 */ 0x00, 0x10, 0x00, 0x00, 0x06, 0x10, 0x00, 0x04,\
+/* 160 */ 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
+/* 168 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,\
+/* 176 */ 0x00, 0x10, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00,\
+/* 184 */ 0x00, 0x00, 0x00,}
+
+/* The resolve3P2Values() routine is able to run faster if it knows
** the value of the largest JUMP opcode. The smaller the maximum
** JUMP opcode the better, so the mkopcodeh.tcl script that
** generated this include file strives to group all JUMP opcodes
** together near the beginning of the list.
*/
-#define SQLITE_MX_JUMP_OPCODE 62 /* Maximum JUMP opcode */
+#define SQLITE_MX_JUMP_OPCODE 64 /* Maximum JUMP opcode */
/************** End of opcodes.h *********************************************/
/************** Continuing where we left off in vdbe.h ***********************/
@@ -15957,8 +15892,10 @@ SQLITE_PRIVATE void sqlcipher_sqlite3VdbeVerifyNoResultRow(Vdbe *p);
#endif
#if defined(SQLITE_DEBUG)
SQLITE_PRIVATE void sqlcipher_sqlite3VdbeVerifyAbortable(Vdbe *p, int);
+SQLITE_PRIVATE void sqlcipher_sqlite3VdbeNoJumpsOutsideSubrtn(Vdbe*,int,int,int);
#else
# define sqlcipher_sqlite3VdbeVerifyAbortable(A,B)
+# define sqlcipher_sqlite3VdbeNoJumpsOutsideSubrtn(A,B,C,D)
#endif
SQLITE_PRIVATE VdbeOp *sqlcipher_sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp,int iLineno);
#ifndef SQLITE_OMIT_EXPLAIN
@@ -15979,7 +15916,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3ExplainBreakpoint(const char*,const char*
#else
# define sqlcipher_sqlite3ExplainBreakpoint(A,B) /*no-op*/
#endif
-SQLITE_PRIVATE void sqlcipher_sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*);
+SQLITE_PRIVATE void sqlcipher_sqlite3VdbeAddParseSchemaOp(Vdbe*, int, char*, u16);
SQLITE_PRIVATE void sqlcipher_sqlite3VdbeChangeOpcode(Vdbe*, int addr, u8);
SQLITE_PRIVATE void sqlcipher_sqlite3VdbeChangeP1(Vdbe*, int addr, int P1);
SQLITE_PRIVATE void sqlcipher_sqlite3VdbeChangeP2(Vdbe*, int addr, int P2);
@@ -16003,7 +15940,6 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VdbeMakeLabel(Parse*);
SQLITE_PRIVATE void sqlcipher_sqlite3VdbeRunOnlyOnce(Vdbe*);
SQLITE_PRIVATE void sqlcipher_sqlite3VdbeReusable(Vdbe*);
SQLITE_PRIVATE void sqlcipher_sqlite3VdbeDelete(Vdbe*);
-SQLITE_PRIVATE void sqlcipher_sqlite3VdbeClearObject(sqlcipher_sqlite3*,Vdbe*);
SQLITE_PRIVATE void sqlcipher_sqlite3VdbeMakeReady(Vdbe*,Parse*);
SQLITE_PRIVATE int sqlcipher_sqlite3VdbeFinalize(Vdbe*);
SQLITE_PRIVATE void sqlcipher_sqlite3VdbeResolveLabel(Vdbe*, int);
@@ -16446,6 +16382,19 @@ SQLITE_PRIVATE int sqlcipher_sqlite3PCacheIsDirty(PCache *pCache);
# define SET_FULLSYNC(x,y)
#endif
+/* Maximum pathname length. Note: FILENAME_MAX defined by stdio.h
+*/
+#ifndef SQLITE_MAX_PATHLEN
+# define SQLITE_MAX_PATHLEN FILENAME_MAX
+#endif
+
+/* Maximum number of symlinks that will be resolved while trying to
+** expand a filename in xFullPathname() in the VFS.
+*/
+#ifndef SQLITE_MAX_SYMLINK
+# define SQLITE_MAX_SYMLINK 200
+#endif
+
/*
** The default size of a disk sector
*/
@@ -16951,6 +16900,11 @@ SQLITE_PRIVATE void sqlcipher_sqlite3CryptFunc(sqlcipher_sqlite3_context*,int,sq
#endif /* SQLITE_OMIT_DEPRECATED */
#define SQLITE_TRACE_NONLEGACY_MASK 0x0f /* Normal flags */
+/*
+** Maximum number of sqlcipher_sqlite3.aDb[] entries. This is the number of attached
+** databases plus 2 for "main" and "temp".
+*/
+#define SQLITE_MAX_DB (SQLITE_MAX_ATTACHED+2)
/*
** Each database connection is an instance of the following structure.
@@ -16969,9 +16923,10 @@ struct sqlcipher_sqlite3 {
u32 nSchemaLock; /* Do not reset the schema when non-zero */
unsigned int openFlags; /* Flags passed to sqlcipher_sqlite3_vfs.xOpen() */
int errCode; /* Most recent error code (SQLITE_*) */
+ int errByteOffset; /* Byte offset of error in SQL statement */
int errMask; /* & result codes with this before returning */
int iSysErrno; /* Errno value from last system error */
- u16 dbOptFlags; /* Flags to enable/disable optimizations */
+ u32 dbOptFlags; /* Flags to enable/disable optimizations */
u8 enc; /* Text encoding */
u8 autoCommit; /* The auto-commit flag. */
u8 temp_store; /* 1: file 2: memory 0: default */
@@ -16985,10 +16940,10 @@ struct sqlcipher_sqlite3 {
u8 mTrace; /* zero or more SQLITE_TRACE flags */
u8 noSharedCache; /* True if no shared-cache backends */
u8 nSqlExec; /* Number of pending OP_SqlExec opcodes */
+ u8 eOpenState; /* Current condition of the connection */
int nextPagesize; /* Pagesize after VACUUM if >0 */
- u32 magic; /* Magic number for detect library misuse */
- int nChange; /* Value returned by sqlcipher_sqlite3_changes() */
- int nTotalChange; /* Value returned by sqlcipher_sqlite3_total_changes() */
+ i64 nChange; /* Value returned by sqlcipher_sqlite3_changes() */
+ i64 nTotalChange; /* Value returned by sqlcipher_sqlite3_total_changes() */
int aLimit[SQLITE_N_LIMIT]; /* Limits */
int nMaxSorterMmap; /* Maximum size of regions mapped by sorter */
struct sqlcipher_sqlite3InitInfo { /* Information used during initialization */
@@ -16998,7 +16953,7 @@ struct sqlcipher_sqlite3 {
unsigned orphanTrigger : 1; /* Last statement is orphaned TEMP trigger */
unsigned imposterTable : 1; /* Building an imposter table */
unsigned reopenMemdb : 1; /* ATTACH is really a reopen using MemDB */
- char **azInit; /* "type", "name", and "tbl_name" columns */
+ const char **azInit; /* "type", "name", and "tbl_name" columns */
} init;
int nVdbeActive; /* Number of VDBEs currently running */
int nVdbeRead; /* Number of active VDBEs that read or write */
@@ -17008,10 +16963,10 @@ struct sqlcipher_sqlite3 {
int nExtension; /* Number of loaded extensions */
void **aExtension; /* Array of shared library handles */
union {
- void (*xLegacy)(void*,const char*); /* Legacy trace function */
- int (*xV2)(u32,void*,void*,void*); /* V2 Trace function */
+ void (*xLegacy)(void*,const char*); /* mTrace==SQLITE_TRACE_LEGACY */
+ int (*xV2)(u32,void*,void*,void*); /* All other mTrace values */
} trace;
- void *pTraceArg; /* Argument to the trace function */
+ void *pTraceArg; /* Argument to the trace function */
#ifndef SQLITE_OMIT_DEPRECATED
void (*xProfile)(void*,const char*,u64); /* Profiling function */
void *pProfileArg; /* Argument to profile function */
@@ -17022,6 +16977,9 @@ struct sqlcipher_sqlite3 {
void (*xRollbackCallback)(void*); /* Invoked at every commit. */
void *pUpdateArg;
void (*xUpdateCallback)(void*,int, const char*,const char*,sqlite_int64);
+ void *pAutovacPagesArg; /* Client argument to autovac_pages */
+ void (*xAutovacDestr)(void*); /* Destructor for pAutovacPAgesArg */
+ unsigned int (*xAutovacPages)(void*,const char*,u32,u32,u32);
Parse *pParse; /* Current parse */
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
void *pPreUpdateArg; /* First argument to xPreUpdateCallback */
@@ -17151,6 +17109,7 @@ struct sqlcipher_sqlite3 {
#define SQLITE_CountRows HI(0x00001) /* Count rows changed by INSERT, */
/* DELETE, or UPDATE and return */
/* the count using a callback. */
+#define SQLITE_CorruptRdOnly HI(0x00002) /* Prohibit writes due to error */
/* Flags used only if debugging */
#ifdef SQLITE_DEBUG
@@ -17178,24 +17137,34 @@ struct sqlcipher_sqlite3 {
** sqlcipher_sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to
** selectively disable various optimizations.
*/
-#define SQLITE_QueryFlattener 0x0001 /* Query flattening */
-#define SQLITE_WindowFunc 0x0002 /* Use xInverse for window functions */
-#define SQLITE_GroupByOrder 0x0004 /* GROUPBY cover of ORDERBY */
-#define SQLITE_FactorOutConst 0x0008 /* Constant factoring */
-#define SQLITE_DistinctOpt 0x0010 /* DISTINCT using indexes */
-#define SQLITE_CoverIdxScan 0x0020 /* Covering index scans */
-#define SQLITE_OrderByIdxJoin 0x0040 /* ORDER BY of joins via index */
-#define SQLITE_Transitive 0x0080 /* Transitive constraints */
-#define SQLITE_OmitNoopJoin 0x0100 /* Omit unused tables in joins */
-#define SQLITE_CountOfView 0x0200 /* The count-of-view optimization */
-#define SQLITE_CursorHints 0x0400 /* Add OP_CursorHint opcodes */
-#define SQLITE_Stat4 0x0800 /* Use STAT4 data */
- /* TH3 expects the Stat4 ^^^^^^ value to be 0x0800. Don't change it */
-#define SQLITE_PushDown 0x1000 /* The push-down optimization */
-#define SQLITE_SimplifyJoin 0x2000 /* Convert LEFT JOIN to JOIN */
-#define SQLITE_SkipScan 0x4000 /* Skip-scans */
-#define SQLITE_PropagateConst 0x8000 /* The constant propagation opt */
-#define SQLITE_AllOpts 0xffff /* All optimizations */
+#define SQLITE_QueryFlattener 0x00000001 /* Query flattening */
+#define SQLITE_WindowFunc 0x00000002 /* Use xInverse for window functions */
+#define SQLITE_GroupByOrder 0x00000004 /* GROUPBY cover of ORDERBY */
+#define SQLITE_FactorOutConst 0x00000008 /* Constant factoring */
+#define SQLITE_DistinctOpt 0x00000010 /* DISTINCT using indexes */
+#define SQLITE_CoverIdxScan 0x00000020 /* Covering index scans */
+#define SQLITE_OrderByIdxJoin 0x00000040 /* ORDER BY of joins via index */
+#define SQLITE_Transitive 0x00000080 /* Transitive constraints */
+#define SQLITE_OmitNoopJoin 0x00000100 /* Omit unused tables in joins */
+#define SQLITE_CountOfView 0x00000200 /* The count-of-view optimization */
+#define SQLITE_CursorHints 0x00000400 /* Add OP_CursorHint opcodes */
+#define SQLITE_Stat4 0x00000800 /* Use STAT4 data */
+ /* TH3 expects this value ^^^^^^^^^^ to be 0x0000800. Don't change it */
+#define SQLITE_PushDown 0x00001000 /* The push-down optimization */
+#define SQLITE_SimplifyJoin 0x00002000 /* Convert LEFT JOIN to JOIN */
+#define SQLITE_SkipScan 0x00004000 /* Skip-scans */
+#define SQLITE_PropagateConst 0x00008000 /* The constant propagation opt */
+#define SQLITE_MinMaxOpt 0x00010000 /* The min/max optimization */
+#define SQLITE_SeekScan 0x00020000 /* The OP_SeekScan optimization */
+#define SQLITE_OmitOrderBy 0x00040000 /* Omit pointless ORDER BY */
+ /* TH3 expects this value ^^^^^^^^^^ to be 0x40000. Coordinate any change */
+#define SQLITE_BloomFilter 0x00080000 /* Use a Bloom filter on searches */
+#define SQLITE_BloomPulldown 0x00100000 /* Run Bloom filters early */
+#define SQLITE_BalancedMerge 0x00200000 /* Balance multi-way merges */
+#define SQLITE_ReleaseReg 0x00400000 /* Use OP_ReleaseReg for testing */
+#define SQLITE_FlttnUnionAll 0x00800000 /* Disable the UNION ALL flattener */
+ /* TH3 expects this value ^^^^^^^^^^ See flatten04.test */
+#define SQLITE_AllOpts 0xffffffff /* All optimizations */
/*
** Macros for testing whether or not optimizations are enabled or disabled.
@@ -17209,17 +17178,16 @@ struct sqlcipher_sqlite3 {
*/
#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.
+/* Possible values for the sqlcipher_sqlite3.eOpenState field.
+** The numbers are randomly selected such that a minimum of three bits must
+** change to convert any number to another or to zero
*/
-#define SQLITE_MAGIC_OPEN 0xa029a697 /* Database is open */
-#define SQLITE_MAGIC_CLOSED 0x9f3c2d33 /* Database is closed */
-#define SQLITE_MAGIC_SICK 0x4b771290 /* Error and awaiting close */
-#define SQLITE_MAGIC_BUSY 0xf03b7906 /* Database currently in use */
-#define SQLITE_MAGIC_ERROR 0xb5357930 /* An SQLITE_MISUSE error occurred */
-#define SQLITE_MAGIC_ZOMBIE 0x64cffc7f /* Close with last statement close */
+#define SQLITE_STATE_OPEN 0x76 /* Database is open */
+#define SQLITE_STATE_CLOSED 0xce /* Database is closed */
+#define SQLITE_STATE_SICK 0xba /* Error and awaiting close */
+#define SQLITE_STATE_BUSY 0x6d /* Database currently in use */
+#define SQLITE_STATE_ERROR 0xd5 /* An SQLITE_MISUSE error occurred */
+#define SQLITE_STATE_ZOMBIE 0xa7 /* Close with last statement close */
/*
** Each SQL function is defined by an instance of the following
@@ -17244,7 +17212,7 @@ struct FuncDef {
union {
FuncDef *pHash; /* Next with a different name but the same hash */
FuncDestructor *pDestructor; /* Reference counted destructor function */
- } u;
+ } u; /* pHash if SQLITE_FUNC_BUILTIN, pDestructor otherwise */
};
/*
@@ -17274,12 +17242,13 @@ struct FuncDestructor {
** are assert() statements in the code to verify this.
**
** Value constraints (enforced via assert()):
-** SQLITE_FUNC_MINMAX == NC_MinMaxAgg == SF_MinMaxAgg
-** SQLITE_FUNC_LENGTH == OPFLAG_LENGTHARG
-** SQLITE_FUNC_TYPEOF == OPFLAG_TYPEOFARG
-** SQLITE_FUNC_CONSTANT == SQLITE_DETERMINISTIC from the API
-** SQLITE_FUNC_DIRECT == SQLITE_DIRECTONLY from the API
-** SQLITE_FUNC_UNSAFE == SQLITE_INNOCUOUS
+** SQLITE_FUNC_MINMAX == NC_MinMaxAgg == SF_MinMaxAgg
+** SQLITE_FUNC_ANYORDER == NC_OrderAgg == SF_OrderByReqd
+** SQLITE_FUNC_LENGTH == OPFLAG_LENGTHARG
+** SQLITE_FUNC_TYPEOF == OPFLAG_TYPEOFARG
+** SQLITE_FUNC_CONSTANT == SQLITE_DETERMINISTIC from the API
+** SQLITE_FUNC_DIRECT == SQLITE_DIRECTONLY from the API
+** SQLITE_FUNC_UNSAFE == SQLITE_INNOCUOUS
** SQLITE_FUNC_ENCMASK depends on SQLITE_UTF* macros in the API
*/
#define SQLITE_FUNC_ENCMASK 0x0003 /* SQLITE_UTF8, SQLITE_UTF16BE or UTF16LE */
@@ -17297,13 +17266,15 @@ struct FuncDestructor {
#define SQLITE_FUNC_SLOCHNG 0x2000 /* "Slow Change". Value constant during a
** single query - might change over time */
#define SQLITE_FUNC_TEST 0x4000 /* Built-in testing functions */
-#define SQLITE_FUNC_OFFSET 0x8000 /* Built-in sqlite_offset() function */
+/* 0x8000 -- available for reuse */
#define SQLITE_FUNC_WINDOW 0x00010000 /* Built-in window-only function */
#define SQLITE_FUNC_INTERNAL 0x00040000 /* For use by NestedParse() only */
#define SQLITE_FUNC_DIRECT 0x00080000 /* Not for use in TRIGGERs or VIEWs */
#define SQLITE_FUNC_SUBTYPE 0x00100000 /* Result likely to have sub-type */
#define SQLITE_FUNC_UNSAFE 0x00200000 /* Function has side effects */
#define SQLITE_FUNC_INLINE 0x00400000 /* Functions implemented in-line */
+#define SQLITE_FUNC_BUILTIN 0x00800000 /* This is a built-in function */
+#define SQLITE_FUNC_ANYORDER 0x08000000 /* count/min/max aggregate */
/* Identifier numbers for each in-line function */
#define INLINEFUNC_coalesce 0
@@ -17312,6 +17283,7 @@ struct FuncDestructor {
#define INLINEFUNC_expr_compare 3
#define INLINEFUNC_affinity 4
#define INLINEFUNC_iif 5
+#define INLINEFUNC_sqlite_offset 6
#define INLINEFUNC_unlikely 99 /* Default case */
/*
@@ -17351,6 +17323,9 @@ struct FuncDestructor {
** a single query. The iArg is ignored. The user-data is always set
** to a NULL pointer. The bNC parameter is not used.
**
+** MFUNCTION(zName, nArg, xPtr, xFunc)
+** For math-library functions. xPtr is an arbitrary pointer.
+**
** PURE_DATE(zName, nArg, iArg, bNC, xFunc)
** Used for "pure" date/time functions, this macro is like DFUNCTION
** except that it does set the SQLITE_FUNC_CONSTANT flags. iArg is
@@ -17363,7 +17338,7 @@ struct FuncDestructor {
** are interpreted in the same way as the first 4 parameters to
** FUNCTION().
**
-** WFUNCTION(zName, nArg, iArg, xStep, xFinal, xValue, xInverse)
+** WAGGREGATE(zName, nArg, iArg, xStep, xFinal, xValue, xInverse)
** Used to create an aggregate function definition implemented by
** the C functions xStep and xFinal. The first four parameters
** are interpreted in the same way as the first 4 parameters to
@@ -17378,41 +17353,55 @@ struct FuncDestructor {
** parameter.
*/
#define FUNCTION(zName, nArg, iArg, bNC, xFunc) \
- {nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
+ {nArg, SQLITE_FUNC_BUILTIN|\
+ SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} }
#define VFUNCTION(zName, nArg, iArg, bNC, xFunc) \
- {nArg, SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
+ {nArg, SQLITE_FUNC_BUILTIN|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} }
#define SFUNCTION(zName, nArg, iArg, bNC, xFunc) \
- {nArg, SQLITE_UTF8|SQLITE_DIRECTONLY|SQLITE_FUNC_UNSAFE, \
+ {nArg, SQLITE_FUNC_BUILTIN|SQLITE_UTF8|SQLITE_DIRECTONLY|SQLITE_FUNC_UNSAFE, \
+ SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} }
+#define MFUNCTION(zName, nArg, xPtr, xFunc) \
+ {nArg, SQLITE_FUNC_BUILTIN|SQLITE_FUNC_CONSTANT|SQLITE_UTF8, \
+ xPtr, 0, xFunc, 0, 0, 0, #zName, {0} }
+#define JFUNCTION(zName, nArg, iArg, xFunc) \
+ {nArg, SQLITE_FUNC_BUILTIN|SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS|\
+ SQLITE_FUNC_CONSTANT|SQLITE_UTF8, \
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} }
#define INLINE_FUNC(zName, nArg, iArg, mFlags) \
- {nArg, SQLITE_UTF8|SQLITE_FUNC_INLINE|SQLITE_FUNC_CONSTANT|(mFlags), \
+ {nArg, SQLITE_FUNC_BUILTIN|\
+ SQLITE_UTF8|SQLITE_FUNC_INLINE|SQLITE_FUNC_CONSTANT|(mFlags), \
SQLITE_INT_TO_PTR(iArg), 0, noopFunc, 0, 0, 0, #zName, {0} }
#define TEST_FUNC(zName, nArg, iArg, mFlags) \
- {nArg, SQLITE_UTF8|SQLITE_FUNC_INTERNAL|SQLITE_FUNC_TEST| \
+ {nArg, SQLITE_FUNC_BUILTIN|\
+ SQLITE_UTF8|SQLITE_FUNC_INTERNAL|SQLITE_FUNC_TEST| \
SQLITE_FUNC_INLINE|SQLITE_FUNC_CONSTANT|(mFlags), \
SQLITE_INT_TO_PTR(iArg), 0, noopFunc, 0, 0, 0, #zName, {0} }
#define DFUNCTION(zName, nArg, iArg, bNC, xFunc) \
- {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8, \
+ {nArg, SQLITE_FUNC_BUILTIN|SQLITE_FUNC_SLOCHNG|SQLITE_UTF8, \
0, 0, xFunc, 0, 0, 0, #zName, {0} }
#define PURE_DATE(zName, nArg, iArg, bNC, xFunc) \
- {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|SQLITE_FUNC_CONSTANT, \
+ {nArg, SQLITE_FUNC_BUILTIN|\
+ SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|SQLITE_FUNC_CONSTANT, \
(void*)&sqlcipher_sqlite3Config, 0, xFunc, 0, 0, 0, #zName, {0} }
#define FUNCTION2(zName, nArg, iArg, bNC, xFunc, extraFlags) \
- {nArg,SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags,\
+ {nArg, SQLITE_FUNC_BUILTIN|\
+ SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags,\
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} }
#define STR_FUNCTION(zName, nArg, pArg, bNC, xFunc) \
- {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
+ {nArg, SQLITE_FUNC_BUILTIN|\
+ SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
pArg, 0, xFunc, 0, 0, 0, #zName, }
#define LIKEFUNC(zName, nArg, arg, flags) \
- {nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|flags, \
+ {nArg, SQLITE_FUNC_BUILTIN|SQLITE_FUNC_CONSTANT|SQLITE_UTF8|flags, \
(void *)arg, 0, likeFunc, 0, 0, 0, #zName, {0} }
#define WAGGREGATE(zName, nArg, arg, nc, xStep, xFinal, xValue, xInverse, f) \
- {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|f, \
+ {nArg, SQLITE_FUNC_BUILTIN|SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|f, \
SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xValue,xInverse,#zName, {0}}
#define INTERNAL_FUNCTION(zName, nArg, xFunc) \
- {nArg, SQLITE_FUNC_INTERNAL|SQLITE_UTF8|SQLITE_FUNC_CONSTANT, \
+ {nArg, SQLITE_FUNC_BUILTIN|\
+ SQLITE_FUNC_INTERNAL|SQLITE_UTF8|SQLITE_FUNC_CONSTANT, \
0, 0, xFunc, 0, 0, 0, #zName, {0} }
@@ -17468,19 +17457,48 @@ struct Module {
** or equal to the table column index. It is
** equal if and only if there are no VIRTUAL
** columns to the left.
+**
+** Notes on zCnName:
+** The zCnName field stores the name of the column, the datatype of the
+** column, and the collating sequence for the column, in that order, all in
+** a single allocation. Each string is 0x00 terminated. The datatype
+** is only included if the COLFLAG_HASTYPE bit of colFlags is set and the
+** collating sequence name is only included if the COLFLAG_HASCOLL bit is
+** set.
*/
struct Column {
- char *zName; /* Name of this column, \000, then the type */
- Expr *pDflt; /* Default value or GENERATED ALWAYS AS value */
- 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 */
- u8 szEst; /* Estimated size of value in this column. sizeof(INT)==1 */
- u8 hName; /* Column name hash for faster lookup */
- u16 colFlags; /* Boolean properties. See COLFLAG_ defines below */
+ char *zCnName; /* Name of this column */
+ unsigned notNull :4; /* An OE_ code for handling a NOT NULL constraint */
+ unsigned eCType :4; /* One of the standard types */
+ char affinity; /* One of the SQLITE_AFF_... values */
+ u8 szEst; /* Est size of value in this column. sizeof(INT)==1 */
+ u8 hName; /* Column name hash for faster lookup */
+ u16 iDflt; /* 1-based index of DEFAULT. 0 means "none" */
+ u16 colFlags; /* Boolean properties. See COLFLAG_ defines below */
};
-/* Allowed values for Column.colFlags:
+/* Allowed values for Column.eCType.
+**
+** Values must match entries in the global constant arrays
+** sqlcipher_sqlite3StdTypeLen[] and sqlcipher_sqlite3StdType[]. Each value is one more
+** than the offset into these arrays for the corresponding name.
+** Adjust the SQLITE_N_STDTYPE value if adding or removing entries.
+*/
+#define COLTYPE_CUSTOM 0 /* Type appended to zName */
+#define COLTYPE_ANY 1
+#define COLTYPE_BLOB 2
+#define COLTYPE_INT 3
+#define COLTYPE_INTEGER 4
+#define COLTYPE_REAL 5
+#define COLTYPE_TEXT 6
+#define SQLITE_N_STDTYPE 6 /* Number of standard types */
+
+/* Allowed values for Column.colFlags.
+**
+** Constraints:
+** TF_HasVirtual == COLFLAG_VIRTUAL
+** TF_HasStored == COLFLAG_STORED
+** TF_HasHidden == COLFLAG_HIDDEN
*/
#define COLFLAG_PRIMKEY 0x0001 /* Column is part of the primary key */
#define COLFLAG_HIDDEN 0x0002 /* A hidden column in a virtual table */
@@ -17491,6 +17509,8 @@ struct Column {
#define COLFLAG_STORED 0x0040 /* GENERATED ALWAYS AS ... STORED */
#define COLFLAG_NOTAVAIL 0x0080 /* STORED column not yet calculated */
#define COLFLAG_BUSY 0x0100 /* Blocks recursion on GENERATED columns */
+#define COLFLAG_HASCOLL 0x0200 /* Has collating sequence name in zCnName */
+#define COLFLAG_NOEXPAND 0x0400 /* Omit this column when expanding "*" */
#define COLFLAG_GENERATED 0x0060 /* Combo: _STORED, _VIRTUAL */
#define COLFLAG_NOINSERT 0x0062 /* Combo: _HIDDEN, _STORED, _VIRTUAL */
@@ -17556,9 +17576,7 @@ struct CollSeq {
** operator is NULL. It is added to certain comparison operators to
** prove that the operands are always NOT NULL.
*/
-#define SQLITE_KEEPNULL 0x08 /* Used by vector == or <> */
#define SQLITE_JUMPIFNULL 0x10 /* jumps if either operand is NULL */
-#define SQLITE_STOREP2 0x20 /* Store result in reg[P2] rather than jump */
#define SQLITE_NULLEQ 0x80 /* NULL=NULL */
#define SQLITE_NOTNULL 0x90 /* Assert that operands are never NULL */
@@ -17622,15 +17640,13 @@ struct VTable {
#define SQLITE_VTABRISK_High 2
/*
-** The schema for each SQL table and view is represented in memory
-** by an instance of the following structure.
+** The schema for each SQL table, virtual table, and view is represented
+** in memory by an instance of the following structure.
*/
struct Table {
char *zName; /* Name of the table or view */
Column *aCol; /* Information about each column */
Index *pIndex; /* List of SQL indexes on this table. */
- Select *pSelect; /* NULL for tables. Points to definition if a view. */
- FKey *pFKey; /* Linked list of all foreign keys in this table */
char *zColAff; /* String defining the affinity of each column */
ExprList *pCheck; /* All CHECK constraints */
/* ... also used as column name list in a VIEW */
@@ -17646,17 +17662,25 @@ struct Table {
LogEst costMult; /* Cost multiplier for using this table */
#endif
u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */
-#ifndef SQLITE_OMIT_ALTERTABLE
- int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */
-#endif
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- int nModuleArg; /* Number of arguments to the module */
- char **azModuleArg; /* 0: module 1: schema 2: vtab name 3...: args */
- VTable *pVTable; /* List of VTable objects. */
-#endif
- Trigger *pTrigger; /* List of triggers stored in pSchema */
+ u8 eTabType; /* 0: normal, 1: virtual, 2: view */
+ union {
+ struct { /* Used by ordinary tables: */
+ int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */
+ FKey *pFKey; /* Linked list of all foreign keys in this table */
+ ExprList *pDfltList; /* DEFAULT clauses on various columns.
+ ** Or the AS clause for generated columns. */
+ } tab;
+ struct { /* Used by views: */
+ Select *pSelect; /* View definition */
+ } view;
+ struct { /* Used by virtual tables only: */
+ int nArg; /* Number of arguments to the module */
+ char **azArg; /* 0: module 1: schema 2: vtab name 3...: args */
+ VTable *p; /* List of VTable objects. */
+ } vtab;
+ } u;
+ Trigger *pTrigger; /* List of triggers on this object */
Schema *pSchema; /* Schema that contains this table */
- Table *pNextZombie; /* Next on the Parse.pZombieTab list */
};
/*
@@ -17670,25 +17694,39 @@ struct Table {
**
** Constraints:
**
-** TF_HasVirtual == COLFLAG_Virtual
-** TF_HasStored == COLFLAG_Stored
-*/
-#define TF_Readonly 0x0001 /* Read-only system table */
-#define TF_Ephemeral 0x0002 /* An ephemeral table */
-#define TF_HasPrimaryKey 0x0004 /* Table has a primary key */
-#define TF_Autoincrement 0x0008 /* Integer primary key is autoincrement */
-#define TF_HasStat1 0x0010 /* nRowLogEst set from sqlite_stat1 */
-#define TF_HasVirtual 0x0020 /* Has one or more VIRTUAL columns */
-#define TF_HasStored 0x0040 /* Has one or more STORED columns */
-#define TF_HasGenerated 0x0060 /* Combo: HasVirtual + HasStored */
-#define TF_WithoutRowid 0x0080 /* No rowid. PRIMARY KEY is the key */
-#define TF_StatsUsed 0x0100 /* Query planner decisions affected by
+** TF_HasVirtual == COLFLAG_VIRTUAL
+** TF_HasStored == COLFLAG_STORED
+** TF_HasHidden == COLFLAG_HIDDEN
+*/
+#define TF_Readonly 0x00000001 /* Read-only system table */
+#define TF_HasHidden 0x00000002 /* Has one or more hidden columns */
+#define TF_HasPrimaryKey 0x00000004 /* Table has a primary key */
+#define TF_Autoincrement 0x00000008 /* Integer primary key is autoincrement */
+#define TF_HasStat1 0x00000010 /* nRowLogEst set from sqlite_stat1 */
+#define TF_HasVirtual 0x00000020 /* Has one or more VIRTUAL columns */
+#define TF_HasStored 0x00000040 /* Has one or more STORED columns */
+#define TF_HasGenerated 0x00000060 /* Combo: HasVirtual + HasStored */
+#define TF_WithoutRowid 0x00000080 /* No rowid. PRIMARY KEY is the key */
+#define TF_StatsUsed 0x00000100 /* Query planner decisions affected by
** Index.aiRowLogEst[] values */
-#define TF_NoVisibleRowid 0x0200 /* No user-visible "rowid" column */
-#define TF_OOOHidden 0x0400 /* Out-of-Order hidden columns */
-#define TF_HasNotNull 0x0800 /* Contains NOT NULL constraints */
-#define TF_Shadow 0x1000 /* True for a shadow table */
-#define TF_HasStat4 0x2000 /* STAT4 info available for this table */
+#define TF_NoVisibleRowid 0x00000200 /* No user-visible "rowid" column */
+#define TF_OOOHidden 0x00000400 /* Out-of-Order hidden columns */
+#define TF_HasNotNull 0x00000800 /* Contains NOT NULL constraints */
+#define TF_Shadow 0x00001000 /* True for a shadow table */
+#define TF_HasStat4 0x00002000 /* STAT4 info available for this table */
+#define TF_Ephemeral 0x00004000 /* An ephemeral table */
+#define TF_Eponymous 0x00008000 /* An eponymous virtual table */
+#define TF_Strict 0x00010000 /* STRICT mode */
+
+/*
+** Allowed values for Table.eTabType
+*/
+#define TABTYP_NORM 0 /* Ordinary table */
+#define TABTYP_VTAB 1 /* Virtual table */
+#define TABTYP_VIEW 2 /* A view */
+
+#define IsView(X) ((X)->eTabType==TABTYP_VIEW)
+#define IsOrdinaryTable(X) ((X)->eTabType==TABTYP_NORM)
/*
** Test to see whether or not a table is a virtual table. This is
@@ -17696,9 +17734,9 @@ struct Table {
** table support is omitted from the build.
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
-# define IsVirtual(X) ((X)->nModuleArg)
+# define IsVirtual(X) ((X)->eTabType==TABTYP_VTAB)
# define ExprIsVtab(X) \
- ((X)->op==TK_COLUMN && (X)->y.pTab!=0 && (X)->y.pTab->nModuleArg)
+ ((X)->op==TK_COLUMN && (X)->y.pTab!=0 && (X)->y.pTab->eTabType==TABTYP_VTAB)
#else
# define IsVirtual(X) 0
# define ExprIsVtab(X) 0
@@ -17785,16 +17823,22 @@ struct FKey {
** is returned. REPLACE means that preexisting database rows that caused
** a UNIQUE constraint violation are removed so that the new insert or
** update can proceed. Processing continues and no error is reported.
+** UPDATE applies to insert operations only and means that the insert
+** is omitted and the DO UPDATE clause of an upsert is run instead.
**
-** RESTRICT, SETNULL, and CASCADE actions apply only to foreign keys.
+** RESTRICT, SETNULL, SETDFLT, and CASCADE actions apply only to foreign keys.
** RESTRICT is the same as ABORT for IMMEDIATE foreign keys and the
** same as ROLLBACK for DEFERRED keys. SETNULL means that the foreign
-** key is set to NULL. CASCADE means that a DELETE or UPDATE of the
+** key is set to NULL. SETDFLT means that the foreign key is set
+** to its default value. CASCADE means that a DELETE or UPDATE of the
** referenced table row is propagated into the row that holds the
** foreign key.
**
+** The OE_Default value is a place holder that means to use whatever
+** conflict resolution algorthm is required from context.
+**
** The following symbolic values are used to record which type
-** of action to take.
+** of conflict resolution action to take.
*/
#define OE_None 0 /* There is no constraint to check */
#define OE_Rollback 1 /* Fail the operation and rollback the transaction */
@@ -17873,6 +17917,11 @@ struct KeyInfo {
struct UnpackedRecord {
KeyInfo *pKeyInfo; /* Collation and sort-order information */
Mem *aMem; /* Values */
+ union {
+ char *z; /* Cache of aMem[0].z for vdbeRecordCompareString() */
+ i64 i; /* Cache of aMem[0].u.i for vdbeRecordCompareInt() */
+ } u;
+ int n; /* Cache of aMem[0].n used by vdbeRecordCompareString() */
u16 nField; /* Number of entries in apMem[] */
i8 default_rc; /* Comparison result if keys are equal */
u8 errCode; /* Error detected by xRecordCompare (CORRUPT or NOMEM) */
@@ -18048,10 +18097,10 @@ struct AggInfo {
FuncDef *pFunc; /* The aggregate function implementation */
int iMem; /* Memory location that acts as accumulator */
int iDistinct; /* Ephemeral table used to enforce DISTINCT */
+ int iDistAddr; /* Address of OP_OpenEphemeral */
} *aFunc;
int nFunc; /* Number of entries in aFunc[] */
u32 selId; /* Select to which this AggInfo belongs */
- AggInfo *pNext; /* Next in list of them all */
};
/*
@@ -18081,10 +18130,10 @@ typedef int ynVar;
** tree.
**
** If the expression is an SQL literal (TK_INTEGER, TK_FLOAT, TK_BLOB,
-** or TK_STRING), then Expr.token contains the text of the SQL literal. If
-** the expression is a variable (TK_VARIABLE), then Expr.token contains the
+** or TK_STRING), then Expr.u.zToken contains the text of the SQL literal. If
+** the expression is a variable (TK_VARIABLE), then Expr.u.zToken contains the
** variable name. Finally, if the expression is an SQL function (TK_FUNCTION),
-** then Expr.token contains the name of the function.
+** then Expr.u.zToken contains the name of the function.
**
** Expr.pRight and Expr.pLeft are the left and right subexpressions of a
** binary operator. Either or both may be NULL.
@@ -18124,7 +18173,7 @@ typedef int ynVar;
** help reduce memory requirements, sometimes an Expr object will be
** truncated. And to reduce the number of memory allocations, sometimes
** two or more Expr objects will be stored in a single memory allocation,
-** together with Expr.zToken strings.
+** together with Expr.u.zToken strings.
**
** If the EP_Reduced and EP_TokenOnly flags are set when
** an Expr object is truncated. When EP_Reduced is set, then all
@@ -18180,7 +18229,10 @@ struct Expr {
** TK_VARIABLE: variable number (always >= 1).
** TK_SELECT_COLUMN: column of the result vector */
i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
- i16 iRightJoinTable; /* If EP_FromJoin, the right table of the join */
+ union {
+ int iJoin; /* If EP_OuterON or EP_InnerON, the right table */
+ int iOfst; /* else: start of token from start of statement */
+ } w;
AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */
union {
Table *pTab; /* TK_COLUMN: Table containing column. Can be NULL
@@ -18193,36 +18245,35 @@ struct Expr {
} y;
};
-/*
-** The following are the meanings of bits in the Expr.flags field.
+/* The following are the meanings of bits in the Expr.flags field.
** Value restrictions:
**
** EP_Agg == NC_HasAgg == SF_HasAgg
** EP_Win == NC_HasWin
*/
-#define EP_FromJoin 0x000001 /* Originates in ON/USING clause of outer join */
-#define EP_Distinct 0x000002 /* Aggregate function with DISTINCT keyword */
-#define EP_HasFunc 0x000004 /* Contains one or more functions of any kind */
-#define EP_FixedCol 0x000008 /* TK_Column with a known fixed value */
+#define EP_OuterON 0x000001 /* Originates in ON/USING clause of outer join */
+#define EP_InnerON 0x000002 /* Originates in ON/USING of an inner join */
+#define EP_Distinct 0x000004 /* Aggregate function with DISTINCT keyword */
+#define EP_HasFunc 0x000008 /* Contains one or more functions of any kind */
#define EP_Agg 0x000010 /* Contains one or more aggregate functions */
-#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_Commuted 0x000200 /* Comparison operator has been commuted */
-#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 /* Operator does not contribute to affinity */
-#define EP_Reduced 0x002000 /* Expr struct EXPR_REDUCEDSIZE bytes only */
-#define EP_TokenOnly 0x004000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */
+#define EP_FixedCol 0x000020 /* TK_Column with a known fixed value */
+#define EP_VarSelect 0x000040 /* pSelect is correlated, not constant */
+#define EP_DblQuoted 0x000080 /* token.z was originally in "..." */
+#define EP_InfixFunc 0x000100 /* True for an infix function: LIKE, GLOB, etc */
+#define EP_Collate 0x000200 /* Tree contains a TK_COLLATE operator */
+#define EP_Commuted 0x000400 /* Comparison operator has been commuted */
+#define EP_IntValue 0x000800 /* Integer value contained in u.iValue */
+#define EP_xIsSelect 0x001000 /* x.pSelect is valid (otherwise x.pList is) */
+#define EP_Skip 0x002000 /* Operator does not contribute to affinity */
+#define EP_Reduced 0x004000 /* Expr struct EXPR_REDUCEDSIZE bytes only */
#define EP_Win 0x008000 /* Contains window functions */
-#define EP_MemToken 0x010000 /* Need to sqlcipher_sqlite3DbFree() Expr.zToken */
-#define EP_IfNullRow 0x020000 /* The TK_IF_NULL_ROW opcode */
-#define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */
-#define EP_ConstFunc 0x080000 /* A SQLITE_FUNC_CONSTANT or _SLOCHNG function */
-#define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */
-#define EP_Subquery 0x200000 /* Tree contains a TK_SELECT operator */
-#define EP_Alias 0x400000 /* Is an alias for a result set column */
+#define EP_TokenOnly 0x010000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */
+#define EP_MemToken 0x020000 /* Need to sqlcipher_sqlite3DbFree() Expr.zToken */
+#define EP_IfNullRow 0x040000 /* The TK_IF_NULL_ROW opcode */
+#define EP_Unlikely 0x080000 /* unlikely() or likelihood() function */
+#define EP_ConstFunc 0x100000 /* A SQLITE_FUNC_CONSTANT or _SLOCHNG function */
+#define EP_CanBeNull 0x200000 /* Can be null despite NOT NULL constraint */
+#define EP_Subquery 0x400000 /* Tree contains a TK_SELECT operator */
#define EP_Leaf 0x800000 /* Expr.pLeft, .pRight, .u.pSelect all NULL */
#define EP_WinFunc 0x1000000 /* TK_FUNCTION with Expr.y.pWin set */
#define EP_Subrtn 0x2000000 /* Uses Expr.y.sub. TK_IN, _SELECT, or _EXISTS */
@@ -18233,23 +18284,31 @@ struct Expr {
#define EP_FromDDL 0x40000000 /* Originates from sqlite_schema */
/* 0x80000000 // Available */
-/*
-** The EP_Propagate mask is a set of properties that automatically propagate
+/* The EP_Propagate mask is a set of properties that automatically propagate
** upwards into parent nodes.
*/
#define EP_Propagate (EP_Collate|EP_Subquery|EP_HasFunc)
-/*
-** These macros can be used to test, set, or clear bits in the
+/* Macros can be used to test, set, or clear bits in the
** Expr.flags field.
*/
#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)
-#define ExprAlwaysTrue(E) (((E)->flags&(EP_FromJoin|EP_IsTrue))==EP_IsTrue)
-#define ExprAlwaysFalse(E) (((E)->flags&(EP_FromJoin|EP_IsFalse))==EP_IsFalse)
+#define ExprAlwaysTrue(E) (((E)->flags&(EP_OuterON|EP_IsTrue))==EP_IsTrue)
+#define ExprAlwaysFalse(E) (((E)->flags&(EP_OuterON|EP_IsFalse))==EP_IsFalse)
+/* Macros used to ensure that the correct members of unions are accessed
+** in Expr.
+*/
+#define ExprUseUToken(E) (((E)->flags&EP_IntValue)==0)
+#define ExprUseUValue(E) (((E)->flags&EP_IntValue)!=0)
+#define ExprUseXList(E) (((E)->flags&EP_xIsSelect)==0)
+#define ExprUseXSelect(E) (((E)->flags&EP_xIsSelect)!=0)
+#define ExprUseYTab(E) (((E)->flags&(EP_WinFunc|EP_Subrtn))==0)
+#define ExprUseYWin(E) (((E)->flags&EP_WinFunc)!=0)
+#define ExprUseYSub(E) (((E)->flags&EP_Subrtn)!=0)
/* Flags for use with Expr.vvaFlags
*/
@@ -18321,21 +18380,29 @@ struct Expr {
*/
struct ExprList {
int nExpr; /* Number of expressions on the list */
+ int nAlloc; /* Number of a[] slots allocated */
struct ExprList_item { /* For each expression in the list */
Expr *pExpr; /* The parse tree for this expression */
char *zEName; /* Token associated with this expression */
- u8 sortFlags; /* Mask of KEYINFO_ORDER_* flags */
- unsigned eEName :2; /* Meaning of zEName */
- unsigned done :1; /* A flag to indicate when processing is finished */
- unsigned reusable :1; /* Constant expression is reusable */
- unsigned bSorterRef :1; /* Defer evaluation until after sorting */
- unsigned bNulls: 1; /* True if explicit "NULLS FIRST/LAST" */
+ struct {
+ u8 sortFlags; /* Mask of KEYINFO_ORDER_* flags */
+ unsigned eEName :2; /* Meaning of zEName */
+ unsigned done :1; /* Indicates when processing is finished */
+ unsigned reusable :1; /* Constant expression is reusable */
+ unsigned bSorterRef :1; /* Defer evaluation until after sorting */
+ unsigned bNulls :1; /* True if explicit "NULLS FIRST/LAST" */
+ unsigned bUsed :1; /* This column used in a SF_NestedFrom subquery */
+ unsigned bUsingTerm:1; /* Term from the USING clause of a NestedFrom */
+ unsigned bNoExpand: 1; /* Term is an auxiliary in NestedFrom and should
+ ** not be expanded by "*" in parent queries */
+ } fg;
union {
- struct {
+ struct { /* Used by any ExprList other than Parse.pConsExpr */
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 */
+ int iConstExprReg; /* Register in which Expr value is cached. Used only
+ ** by Parse.pConstExpr */
} u;
} a[1]; /* One slot for each expression in the list */
};
@@ -18363,11 +18430,86 @@ struct ExprList {
** If "a" is the k-th column of table "t", then IdList.a[0].idx==k.
*/
struct IdList {
+ int nId; /* Number of identifiers on the list */
+ u8 eU4; /* Which element of a.u4 is valid */
struct IdList_item {
char *zName; /* Name of the identifier */
- int idx; /* Index in some Table.aCol[] of a column named zName */
- } *a;
- int nId; /* Number of identifiers on the list */
+ union {
+ int idx; /* Index in some Table.aCol[] of a column named zName */
+ Expr *pExpr; /* Expr to implement a USING variable -- NOT USED */
+ } u4;
+ } a[1];
+};
+
+/*
+** Allowed values for IdList.eType, which determines which value of the a.u4
+** is valid.
+*/
+#define EU4_NONE 0 /* Does not use IdList.a.u4 */
+#define EU4_IDX 1 /* Uses IdList.a.u4.idx */
+#define EU4_EXPR 2 /* Uses IdList.a.u4.pExpr -- NOT CURRENTLY USED */
+
+/*
+** The SrcItem object represents a single term in the FROM clause of a query.
+** The SrcList object is mostly an array of SrcItems.
+**
+** Union member validity:
+**
+** u1.zIndexedBy fg.isIndexedBy && !fg.isTabFunc
+** u1.pFuncArg fg.isTabFunc && !fg.isIndexedBy
+** u2.pIBIndex fg.isIndexedBy && !fg.isCte
+** u2.pCteUse fg.isCte && !fg.isIndexedBy
+*/
+struct SrcItem {
+ Schema *pSchema; /* Schema to which this item is fixed */
+ char *zDatabase; /* Name of database holding this table */
+ char *zName; /* Name of the table */
+ char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */
+ Table *pTab; /* An SQL table corresponding to zName */
+ Select *pSelect; /* A SELECT statement used in place of a table name */
+ int 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 */
+ struct {
+ u8 jointype; /* Type of join between this table and the previous */
+ unsigned notIndexed :1; /* True if there is a NOT INDEXED clause */
+ unsigned isIndexedBy :1; /* True if there is an INDEXED BY clause */
+ unsigned isTabFunc :1; /* True if table-valued-function syntax */
+ unsigned isCorrelated :1; /* True if sub-query is correlated */
+ unsigned isMaterialized:1; /* This is a materialized view */
+ unsigned viaCoroutine :1; /* Implemented as a co-routine */
+ unsigned isRecursive :1; /* True for recursive reference in WITH */
+ unsigned fromDDL :1; /* Comes from sqlite_schema */
+ unsigned isCte :1; /* This is a CTE */
+ unsigned notCte :1; /* This item may not match a CTE */
+ unsigned isUsing :1; /* u3.pUsing is valid */
+ unsigned isOn :1; /* u3.pOn was once valid and non-NULL */
+ unsigned isSynthUsing :1; /* u3.pUsing is synthensized from NATURAL */
+ unsigned isNestedFrom :1; /* pSelect is a SF_NestedFrom subquery */
+ } fg;
+ int iCursor; /* The VDBE cursor number used to access this table */
+ union {
+ Expr *pOn; /* fg.isUsing==0 => The ON clause of a join */
+ IdList *pUsing; /* fg.isUsing==1 => The USING clause of a join */
+ } u3;
+ Bitmask colUsed; /* Bit N (1<<N) set if column N of pTab is used */
+ union {
+ char *zIndexedBy; /* Identifier from "INDEXED BY <zIndex>" clause */
+ ExprList *pFuncArg; /* Arguments to table-valued-function */
+ } u1;
+ union {
+ Index *pIBIndex; /* Index structure corresponding to u1.zIndexedBy */
+ CteUse *pCteUse; /* CTE Usage info info fg.isCte is true */
+ } u2;
+};
+
+/*
+** The OnOrUsing object represents either an ON clause or a USING clause.
+** It can never be both at the same time, but it can be neither.
+*/
+struct OnOrUsing {
+ Expr *pOn; /* The ON clause of a join */
+ IdList *pUsing; /* The USING clause of a join */
};
/*
@@ -18392,49 +18534,21 @@ struct IdList {
struct SrcList {
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 */
- char *zName; /* Name of the table */
- char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */
- Table *pTab; /* An SQL table corresponding to zName */
- Select *pSelect; /* A SELECT statement used in place of a table name */
- int 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 */
- struct {
- u8 jointype; /* Type of join between this table and the previous */
- unsigned notIndexed :1; /* True if there is a NOT INDEXED clause */
- unsigned isIndexedBy :1; /* True if there is an INDEXED BY clause */
- unsigned isTabFunc :1; /* True if table-valued-function syntax */
- 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 */
- unsigned fromDDL :1; /* Comes from sqlite_schema */
- } fg;
- int iCursor; /* The VDBE cursor number used to access this table */
- Expr *pOn; /* The ON clause of a join */
- IdList *pUsing; /* The USING clause of a join */
- Bitmask colUsed; /* Bit N (1<<N) set if column N of pTab is used */
- union {
- char *zIndexedBy; /* Identifier from "INDEXED BY <zIndex>" clause */
- ExprList *pFuncArg; /* Arguments to table-valued-function */
- } u1;
- Index *pIBIndex; /* Index structure corresponding to u1.zIndexedBy */
- } a[1]; /* One entry for each identifier on the list */
+ SrcItem a[1]; /* One entry for each identifier on the list */
};
/*
** Permitted values of the SrcList.a.jointype field
*/
-#define JT_INNER 0x0001 /* Any kind of inner or cross join */
-#define JT_CROSS 0x0002 /* Explicit use of the CROSS keyword */
-#define JT_NATURAL 0x0004 /* True for a "natural" join */
-#define JT_LEFT 0x0008 /* Left outer join */
-#define JT_RIGHT 0x0010 /* Right outer join */
-#define JT_OUTER 0x0020 /* The "OUTER" keyword is present */
-#define JT_ERROR 0x0040 /* unknown or unsupported join type */
-
+#define JT_INNER 0x01 /* Any kind of inner or cross join */
+#define JT_CROSS 0x02 /* Explicit use of the CROSS keyword */
+#define JT_NATURAL 0x04 /* True for a "natural" join */
+#define JT_LEFT 0x08 /* Left outer join */
+#define JT_RIGHT 0x10 /* Right outer join */
+#define JT_OUTER 0x20 /* The "OUTER" keyword is present */
+#define JT_LTORJ 0x40 /* One of the LEFT operands of a RIGHT JOIN
+ ** Mnemonic: Left Table Of Right Join */
+#define JT_ERROR 0x80 /* unknown or unsupported join type */
/*
** Flags appropriate for the wctrlFlags parameter of sqlcipher_sqlite3WhereBegin()
@@ -18455,9 +18569,9 @@ struct SrcList {
#define WHERE_DISTINCTBY 0x0080 /* pOrderby is really a DISTINCT clause */
#define WHERE_WANT_DISTINCT 0x0100 /* All output needs to be distinct */
#define WHERE_SORTBYGROUP 0x0200 /* Support sqlcipher_sqlite3WhereIsSorted() */
- /* 0x0400 not currently used */
+#define WHERE_AGG_DISTINCT 0x0400 /* Query is "SELECT agg(DISTINCT ...)" */
#define WHERE_ORDERBY_LIMIT 0x0800 /* ORDERBY+LIMIT on the inner loop */
- /* 0x1000 not currently used */
+#define WHERE_RIGHT_JOIN 0x1000 /* Processing a RIGHT JOIN */
/* 0x2000 not currently used */
#define WHERE_USE_LIMIT 0x4000 /* Use the LIMIT in cost estimates */
/* 0x8000 not currently used */
@@ -18497,10 +18611,11 @@ struct NameContext {
ExprList *pEList; /* Optional list of result-set columns */
AggInfo *pAggInfo; /* Information about aggregates at this level */
Upsert *pUpsert; /* ON CONFLICT clause information from an upsert */
+ int iBaseReg; /* For TK_REGISTER when parsing RETURNING */
} uNC;
NameContext *pNext; /* Next outer name context. NULL for outermost */
int nRef; /* Number of names resolved by this context */
- int nErr; /* Number of errors encountered while resolving names */
+ int nNcErr; /* Number of errors encountered while resolving names */
int ncFlags; /* Zero or more NC_* flags defined below */
Select *pWinSelect; /* SELECT statement for any window functions */
};
@@ -18509,29 +18624,33 @@ struct NameContext {
** Allowed values for the NameContext, ncFlags field.
**
** Value constraints (all checked via assert()):
-** NC_HasAgg == SF_HasAgg == EP_Agg
-** NC_MinMaxAgg == SF_MinMaxAgg == SQLITE_FUNC_MINMAX
+** NC_HasAgg == SF_HasAgg == EP_Agg
+** NC_MinMaxAgg == SF_MinMaxAgg == SQLITE_FUNC_MINMAX
+** NC_OrderAgg == SF_OrderByReqd == SQLITE_FUNC_ANYORDER
** NC_HasWin == EP_Win
**
*/
-#define NC_AllowAgg 0x00001 /* Aggregate functions are allowed here */
-#define NC_PartIdx 0x00002 /* True if resolving a partial index WHERE */
-#define NC_IsCheck 0x00004 /* True if resolving a CHECK constraint */
-#define NC_GenCol 0x00008 /* True for a GENERATED ALWAYS AS clause */
-#define NC_HasAgg 0x00010 /* One or more aggregate functions seen */
-#define NC_IdxExpr 0x00020 /* True if resolving columns of CREATE INDEX */
-#define NC_SelfRef 0x0002e /* Combo: PartIdx, isCheck, GenCol, and IdxExpr */
-#define NC_VarSelect 0x00040 /* A correlated subquery has been seen */
-#define NC_UEList 0x00080 /* True if uNC.pEList is used */
-#define NC_UAggInfo 0x00100 /* True if uNC.pAggInfo is used */
-#define NC_UUpsert 0x00200 /* True if uNC.pUpsert is used */
-#define NC_MinMaxAgg 0x01000 /* min/max aggregates seen. See note above */
-#define NC_Complex 0x02000 /* True if a function or subquery seen */
-#define NC_AllowWin 0x04000 /* Window functions are allowed here */
-#define NC_HasWin 0x08000 /* One or more window functions seen */
-#define NC_IsDDL 0x10000 /* Resolving names in a CREATE statement */
-#define NC_InAggFunc 0x20000 /* True if analyzing arguments to an agg func */
-#define NC_FromDDL 0x40000 /* SQL text comes from sqlite_schema */
+#define NC_AllowAgg 0x000001 /* Aggregate functions are allowed here */
+#define NC_PartIdx 0x000002 /* True if resolving a partial index WHERE */
+#define NC_IsCheck 0x000004 /* True if resolving a CHECK constraint */
+#define NC_GenCol 0x000008 /* True for a GENERATED ALWAYS AS clause */
+#define NC_HasAgg 0x000010 /* One or more aggregate functions seen */
+#define NC_IdxExpr 0x000020 /* True if resolving columns of CREATE INDEX */
+#define NC_SelfRef 0x00002e /* Combo: PartIdx, isCheck, GenCol, and IdxExpr */
+#define NC_VarSelect 0x000040 /* A correlated subquery has been seen */
+#define NC_UEList 0x000080 /* True if uNC.pEList is used */
+#define NC_UAggInfo 0x000100 /* True if uNC.pAggInfo is used */
+#define NC_UUpsert 0x000200 /* True if uNC.pUpsert is used */
+#define NC_UBaseReg 0x000400 /* True if uNC.iBaseReg is used */
+#define NC_MinMaxAgg 0x001000 /* min/max aggregates seen. See note above */
+#define NC_Complex 0x002000 /* True if a function or subquery seen */
+#define NC_AllowWin 0x004000 /* Window functions are allowed here */
+#define NC_HasWin 0x008000 /* One or more window functions seen */
+#define NC_IsDDL 0x010000 /* Resolving names in a CREATE statement */
+#define NC_InAggFunc 0x020000 /* True if analyzing arguments to an agg func */
+#define NC_FromDDL 0x040000 /* SQL text comes from sqlite_schema */
+#define NC_NoSelect 0x080000 /* Do not descend into sub-selects */
+#define NC_OrderAgg 0x8000000 /* Has an aggregate other than count/min/max */
/*
** An instance of the following object describes a single ON CONFLICT
@@ -18548,15 +18667,21 @@ struct NameContext {
** WHERE clause is omitted.
*/
struct Upsert {
- ExprList *pUpsertTarget; /* Optional description of conflicting index */
+ ExprList *pUpsertTarget; /* Optional description of conflict target */
Expr *pUpsertTargetWhere; /* WHERE clause for partial index targets */
ExprList *pUpsertSet; /* The SET clause from an ON CONFLICT UPDATE */
Expr *pUpsertWhere; /* WHERE clause for the ON CONFLICT UPDATE */
- /* The fields above comprise the parse tree for the upsert clause.
- ** The fields below are used to transfer information from the INSERT
- ** processing down into the UPDATE processing while generating code.
- ** Upsert owns the memory allocated above, but not the memory below. */
- Index *pUpsertIdx; /* Constraint that pUpsertTarget identifies */
+ Upsert *pNextUpsert; /* Next ON CONFLICT clause in the list */
+ u8 isDoUpdate; /* True for DO UPDATE. False for DO NOTHING */
+ /* Above this point is the parse tree for the ON CONFLICT clauses.
+ ** The next group of fields stores intermediate data. */
+ void *pToFree; /* Free memory when deleting the Upsert object */
+ /* All fields above are owned by the Upsert object and must be freed
+ ** when the Upsert is destroyed. The fields below are used to transfer
+ ** information from the INSERT processing down into the UPDATE processing
+ ** while generating code. The fields below are owned by the INSERT
+ ** statement and will be freed by INSERT processing. */
+ Index *pUpsertIdx; /* UNIQUE constraint specified by pUpsertTarget */
SrcList *pUpsertSrc; /* Table to be updated */
int regData; /* First register holding array of VALUES */
int iDataCur; /* Index of the data cursor */
@@ -18608,9 +18733,10 @@ struct Select {
** "Select Flag".
**
** Value constraints (all checked via assert())
-** SF_HasAgg == NC_HasAgg
-** SF_MinMaxAgg == NC_MinMaxAgg == SQLITE_FUNC_MINMAX
-** SF_FixedLimit == WHERE_USE_LIMIT
+** SF_HasAgg == NC_HasAgg
+** SF_MinMaxAgg == NC_MinMaxAgg == SQLITE_FUNC_MINMAX
+** SF_OrderByReqd == NC_OrderAgg == SQLITE_FUNC_ANYORDER
+** SF_FixedLimit == WHERE_USE_LIMIT
*/
#define SF_Distinct 0x0000001 /* Output should be DISTINCT */
#define SF_All 0x0000002 /* Includes the ALL keyword */
@@ -18635,7 +18761,14 @@ struct Select {
#define SF_WinRewrite 0x0100000 /* Window function rewrite accomplished */
#define SF_View 0x0200000 /* SELECT statement is a view */
#define SF_NoopOrderBy 0x0400000 /* ORDER BY is ignored for this query */
-#define SF_UpdateFrom 0x0800000 /* Statement is an UPDATE...FROM */
+#define SF_UFSrcCheck 0x0800000 /* Check pSrc as required by UPDATE...FROM */
+#define SF_PushDown 0x1000000 /* SELECT has be modified by push-down opt */
+#define SF_MultiPart 0x2000000 /* Has multiple incompatible PARTITIONs */
+#define SF_CopyCte 0x4000000 /* SELECT statement is a copy of a CTE */
+#define SF_OrderByReqd 0x8000000 /* The ORDER BY clause may not be omitted */
+
+/* True if S exists and has SF_NestedFrom */
+#define IsNestedFrom(S) ((S)!=0 && ((S)->selFlags&SF_NestedFrom)!=0)
/*
** The results of a SELECT can be distributed in several ways, as defined
@@ -18807,6 +18940,17 @@ struct TriggerPrg {
#endif
/*
+** An instance of the ParseCleanup object specifies an operation that
+** should be performed after parsing to deallocation resources obtained
+** during the parse and which are no longer needed.
+*/
+struct ParseCleanup {
+ ParseCleanup *pNext; /* Next cleanup task */
+ void *pPtr; /* Pointer to object to deallocate */
+ void (*xCleanup)(sqlcipher_sqlite3*,void*); /* Deallocation routine */
+};
+
+/*
** An SQL parser context. A copy of this structure is passed through
** the parser and down into all the parser action routine in order to
** carry around information that is global to the entire parse.
@@ -18837,6 +18981,10 @@ struct Parse {
u8 okConstFactor; /* OK to factor out constants */
u8 disableLookaside; /* Number of times lookaside has been disabled */
u8 disableVtab; /* Disable all virtual tables for this parse */
+ u8 withinRJSubrtn; /* Nesting level for RIGHT JOIN body subroutines */
+#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
+ u8 earlyCleanup; /* OOM inside sqlcipher_sqlite3ParserAddCleanup() */
+#endif
int nRangeReg; /* Size of the temporary register block */
int iRangeReg; /* First register in temporary register block */
int nErr; /* Number of errors seen */
@@ -18863,13 +19011,17 @@ struct Parse {
AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */
Parse *pToplevel; /* Parse structure for main program (or NULL) */
Table *pTriggerTab; /* Table triggers are being coded for */
- Parse *pParentParse; /* Parent parser if this parser is nested */
- AggInfo *pAggList; /* List of all AggInfo objects */
- int addrCrTab; /* Address of OP_CreateBtree opcode on CREATE TABLE */
+ TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */
+ ParseCleanup *pCleanup; /* List of cleanup operations to run after parse */
+ union {
+ int addrCrTab; /* Address of OP_CreateBtree on CREATE TABLE */
+ Returning *pReturning; /* The RETURNING clause */
+ } u1;
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 bReturning; /* Coding a RETURNING trigger */
u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */
u8 disableTriggers; /* True to disable triggers */
@@ -18881,6 +19033,7 @@ struct Parse {
**************************************************************************/
int aTempReg[8]; /* Holding area for temporary registers */
+ Parse *pOuterParse; /* Outer Parse object when nested */
Token sNameToken; /* Token with unqualified schema object name */
/************************************************************************
@@ -18915,15 +19068,14 @@ struct Parse {
Token sArg; /* Complete text of a module argument */
Table **apVtabLock; /* Pointer to virtual tables needing locking */
#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 */
- With *pWithToFree; /* Free this WITH object at the end of the parse */
#ifndef SQLITE_OMIT_ALTERTABLE
RenameToken *pRename; /* Tokens subject to renaming by ALTER TABLE */
#endif
};
+/* Allowed values for Parse.eParseMode
+*/
#define PARSE_MODE_NORMAL 0
#define PARSE_MODE_DECLARE_VTAB 1
#define PARSE_MODE_RENAME 2
@@ -18932,7 +19084,8 @@ struct Parse {
/*
** Sizes and pointers of various parts of the Parse object.
*/
-#define PARSE_HDR_SZ offsetof(Parse,aTempReg) /* Recursive part w/o aColCache*/
+#define PARSE_HDR(X) (((char*)(X))+offsetof(Parse,zErrMsg))
+#define PARSE_HDR_SZ (offsetof(Parse,aTempReg)-offsetof(Parse,zErrMsg)) /* Recursive part w/o aColCache*/
#define PARSE_RECURSE_SZ offsetof(Parse,sLastToken) /* Recursive part */
#define PARSE_TAIL_SZ (sizeof(Parse)-PARSE_RECURSE_SZ) /* Non-recursive part */
#define PARSE_TAIL(X) (((char*)(X))+PARSE_RECURSE_SZ) /* Pointer to tail */
@@ -18998,27 +19151,29 @@ struct AuthContext {
#define OPFLAG_SAVEPOSITION 0x02 /* OP_Delete/Insert: save cursor pos */
#define OPFLAG_AUXDELETE 0x04 /* OP_Delete: index in a DELETE op */
#define OPFLAG_NOCHNG_MAGIC 0x6d /* OP_MakeRecord: serialtype 10 is ok */
+#define OPFLAG_PREFORMAT 0x80 /* OP_Insert uses preformatted cell */
/*
- * Each trigger present in the database schema is stored as an instance of
- * struct Trigger.
- *
- * Pointers to instances of struct Trigger are stored in two ways.
- * 1. In the "trigHash" hash table (part of the sqlcipher_sqlite3* that represents the
- * database). This allows Trigger structures to be retrieved by name.
- * 2. All triggers associated with a single table form a linked list, using the
- * pNext member of struct Trigger. A pointer to the first element of the
- * linked list is stored as the "pTrigger" member of the associated
- * struct Table.
- *
- * The "step_list" member points to the first element of a linked list
- * containing the SQL statements specified as the trigger program.
- */
+** Each trigger present in the database schema is stored as an instance of
+** struct Trigger.
+**
+** Pointers to instances of struct Trigger are stored in two ways.
+** 1. In the "trigHash" hash table (part of the sqlcipher_sqlite3* that represents the
+** database). This allows Trigger structures to be retrieved by name.
+** 2. All triggers associated with a single table form a linked list, using the
+** pNext member of struct Trigger. A pointer to the first element of the
+** linked list is stored as the "pTrigger" member of the associated
+** struct Table.
+**
+** The "step_list" member points to the first element of a linked list
+** containing the SQL statements specified as the trigger program.
+*/
struct Trigger {
char *zName; /* The name of the trigger */
char *table; /* The table or view to which the trigger applies */
u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT */
u8 tr_tm; /* One of TRIGGER_BEFORE, TRIGGER_AFTER */
+ u8 bReturning; /* This trigger implements a RETURNING clause */
Expr *pWhen; /* The WHEN clause of the expression (may be NULL) */
IdList *pColumns; /* If this is an UPDATE OF <column-list> trigger,
the <column-list> is stored here */
@@ -19039,52 +19194,58 @@ struct Trigger {
#define TRIGGER_AFTER 2
/*
- * An instance of struct TriggerStep is used to store a single SQL statement
- * that is a part of a trigger-program.
- *
- * Instances of struct TriggerStep are stored in a singly linked list (linked
- * using the "pNext" member) referenced by the "step_list" member of the
- * associated struct Trigger instance. The first element of the linked list is
- * the first step of the trigger-program.
- *
- * The "op" member indicates whether this is a "DELETE", "INSERT", "UPDATE" or
- * "SELECT" statement. The meanings of the other members is determined by the
- * value of "op" as follows:
- *
- * (op == TK_INSERT)
- * orconf -> stores the ON CONFLICT algorithm
- * pSelect -> If this is an INSERT INTO ... SELECT ... statement, then
- * this stores a pointer to the SELECT statement. Otherwise NULL.
- * zTarget -> Dequoted name of the table to insert into.
- * pExprList -> If this is an INSERT INTO ... VALUES ... statement, then
- * this stores values to be inserted. Otherwise NULL.
- * pIdList -> If this is an INSERT INTO ... (<column-names>) VALUES ...
- * statement, then this stores the column-names to be
- * inserted into.
- *
- * (op == TK_DELETE)
- * zTarget -> Dequoted name of the table to delete from.
- * pWhere -> The WHERE clause of the DELETE statement if one is specified.
- * Otherwise NULL.
- *
- * (op == TK_UPDATE)
- * zTarget -> Dequoted name of the table to update.
- * pWhere -> The WHERE clause of the UPDATE statement if one is specified.
- * Otherwise NULL.
- * pExprList -> A list of the columns to update and the expressions to update
- * them to. See sqlcipher_sqlite3Update() documentation of "pChanges"
- * argument.
- *
- */
+** An instance of struct TriggerStep is used to store a single SQL statement
+** that is a part of a trigger-program.
+**
+** Instances of struct TriggerStep are stored in a singly linked list (linked
+** using the "pNext" member) referenced by the "step_list" member of the
+** associated struct Trigger instance. The first element of the linked list is
+** the first step of the trigger-program.
+**
+** The "op" member indicates whether this is a "DELETE", "INSERT", "UPDATE" or
+** "SELECT" statement. The meanings of the other members is determined by the
+** value of "op" as follows:
+**
+** (op == TK_INSERT)
+** orconf -> stores the ON CONFLICT algorithm
+** pSelect -> The content to be inserted - either a SELECT statement or
+** a VALUES clause.
+** zTarget -> Dequoted name of the table to insert into.
+** pIdList -> If this is an INSERT INTO ... (<column-names>) VALUES ...
+** statement, then this stores the column-names to be
+** inserted into.
+** pUpsert -> The ON CONFLICT clauses for an Upsert
+**
+** (op == TK_DELETE)
+** zTarget -> Dequoted name of the table to delete from.
+** pWhere -> The WHERE clause of the DELETE statement if one is specified.
+** Otherwise NULL.
+**
+** (op == TK_UPDATE)
+** zTarget -> Dequoted name of the table to update.
+** pWhere -> The WHERE clause of the UPDATE statement if one is specified.
+** Otherwise NULL.
+** pExprList -> A list of the columns to update and the expressions to update
+** them to. See sqlcipher_sqlite3Update() documentation of "pChanges"
+** argument.
+**
+** (op == TK_SELECT)
+** pSelect -> The SELECT statement
+**
+** (op == TK_RETURNING)
+** pExprList -> The list of expressions that follow the RETURNING keyword.
+**
+*/
struct TriggerStep {
- u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT, TK_SELECT */
+ u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT, TK_SELECT,
+ ** or TK_RETURNING */
u8 orconf; /* OE_Rollback etc. */
Trigger *pTrig; /* The trigger that this step is a part of */
Select *pSelect; /* SELECT statement or RHS of INSERT INTO SELECT ... */
char *zTarget; /* Target table for DELETE, UPDATE, INSERT */
SrcList *pFrom; /* FROM clause for UPDATE statement (if any) */
Expr *pWhere; /* The WHERE clause for DELETE or UPDATE steps */
- ExprList *pExprList; /* SET clause for UPDATE */
+ ExprList *pExprList; /* SET clause for UPDATE, or RETURNING clause */
IdList *pIdList; /* Column names for INSERT */
Upsert *pUpsert; /* Upsert clauses on an INSERT */
char *zSpan; /* Original SQL text of this command */
@@ -19093,18 +19254,16 @@ struct TriggerStep {
};
/*
-** The following structure contains information used by the sqliteFix...
-** routines as they walk the parse tree to make database references
-** explicit.
+** Information about a RETURNING clause
*/
-typedef struct DbFixer DbFixer;
-struct DbFixer {
- Parse *pParse; /* The parsing context. Error messages written here */
- Schema *pSchema; /* Fix items to this schema */
- u8 bTemp; /* True for TEMP schema entries */
- 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 */
+struct Returning {
+ Parse *pParse; /* The parse that includes the RETURNING clause */
+ ExprList *pReturnEL; /* List of expressions to return */
+ Trigger retTrig; /* The transient trigger that implements RETURNING */
+ TriggerStep retTStep; /* The trigger step */
+ int iRetCur; /* Transient table holding RETURNING results */
+ int nRetCol; /* Number of in pReturnEL after expansion */
+ int iRetReg; /* Register array for holding a row of RETURNING */
};
/*
@@ -19144,7 +19303,26 @@ typedef struct {
/*
** Allowed values for mInitFlags
*/
-#define INITFLAG_AlterTable 0x0001 /* This is a reparse after ALTER TABLE */
+#define INITFLAG_AlterMask 0x0003 /* Types of ALTER */
+#define INITFLAG_AlterRename 0x0001 /* Reparse after a RENAME */
+#define INITFLAG_AlterDrop 0x0002 /* Reparse after a DROP COLUMN */
+#define INITFLAG_AlterAdd 0x0003 /* Reparse after an ADD COLUMN */
+
+/* Tuning parameters are set using SQLITE_TESTCTRL_TUNE and are controlled
+** on debug-builds of the CLI using ".testctrl tune ID VALUE". Tuning
+** parameters are for temporary use during development, to help find
+** optimial values for parameters in the query planner. The should not
+** be used on trunk check-ins. They are a temporary mechanism available
+** for transient development builds only.
+**
+** Tuning parameters are numbered starting with 1.
+*/
+#define SQLITE_NTUNE 6 /* Should be zero for all trunk check-ins */
+#ifdef SQLITE_DEBUG
+# define Tuning(X) (sqlcipher_sqlite3Config.aTune[(X)-1])
+#else
+# define Tuning(X) 0
+#endif
/*
** Structure containing global configuration data for the SQLite library.
@@ -19200,16 +19378,21 @@ struct Sqlite3Config {
void (*xVdbeBranch)(void*,unsigned iSrcLine,u8 eThis,u8 eMx); /* Callback */
void *pVdbeBranchArg; /* 1st argument */
#endif
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
sqlcipher_sqlite3_int64 mxMemdbSize; /* Default max memdb size */
#endif
#ifndef SQLITE_UNTESTABLE
int (*xTestCallback)(int); /* Invoked by sqlcipher_sqlite3FaultSim() */
#endif
int bLocaltimeFault; /* True to fail localtime() calls */
+ int (*xAltLocaltime)(const void*,void*); /* Alternative localtime() routine */
int iOnceResetThreshold; /* When to reset OP_Once counters */
u32 szSorterRef; /* Min size in bytes to use sorter-refs */
unsigned int iPrngSeed; /* Alternative fixed seed for the PRNG */
+ /* vvvv--- must be last ---vvv */
+#ifdef SQLITE_DEBUG
+ sqlcipher_sqlite3_int64 aTune[SQLITE_NTUNE]; /* Tuning parameters */
+#endif
};
/*
@@ -19245,8 +19428,8 @@ struct Walker {
int n; /* A counter */
int iCur; /* A cursor number */
SrcList *pSrcList; /* FROM clause */
- struct SrcCount *pSrcCount; /* Counting column references */
struct CCurHint *pCCurHint; /* Used by codeCursorHint() */
+ struct RefSrcList *pRefSrcList; /* sqlcipher_sqlite3ReferencesSrcList() */
int *aiCol; /* array of column indexes */
struct IdxCover *pIdxCover; /* Check for index coverage */
struct IdxExprTrans *pIdxTrans; /* Convert idxed expr to column */
@@ -19256,10 +19439,26 @@ struct Walker {
struct WhereConst *pConst; /* WHERE clause constants */
struct RenameCtx *pRename; /* RENAME COLUMN context */
struct Table *pTab; /* Table of generated column */
- struct SrcList_item *pSrcItem; /* A single FROM clause item */
+ SrcItem *pSrcItem; /* A single FROM clause item */
+ DbFixer *pFix;
} u;
};
+/*
+** The following structure contains information used by the sqliteFix...
+** routines as they walk the parse tree to make database references
+** explicit.
+*/
+struct DbFixer {
+ Parse *pParse; /* The parsing context. Error messages written here */
+ Walker w; /* Walker object */
+ Schema *pSchema; /* Fix items to this schema */
+ u8 bTemp; /* True for TEMP schema entries */
+ 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 */
+};
+
/* Forward declarations */
SQLITE_PRIVATE int sqlcipher_sqlite3WalkExpr(Walker*, Expr*);
SQLITE_PRIVATE int sqlcipher_sqlite3WalkExprList(Walker*, ExprList*);
@@ -19271,11 +19470,18 @@ SQLITE_PRIVATE int sqlcipher_sqlite3SelectWalkNoop(Walker*, Select*);
SQLITE_PRIVATE int sqlcipher_sqlite3SelectWalkFail(Walker*, Select*);
SQLITE_PRIVATE int sqlcipher_sqlite3WalkerDepthIncrease(Walker*,Select*);
SQLITE_PRIVATE void sqlcipher_sqlite3WalkerDepthDecrease(Walker*,Select*);
+SQLITE_PRIVATE void sqlcipher_sqlite3WalkWinDefnDummyCallback(Walker*,Select*);
#ifdef SQLITE_DEBUG
SQLITE_PRIVATE void sqlcipher_sqlite3SelectWalkAssert2(Walker*, Select*);
#endif
+#ifndef SQLITE_OMIT_CTE
+SQLITE_PRIVATE void sqlcipher_sqlite3SelectPopWith(Walker*, Select*);
+#else
+# define sqlcipher_sqlite3SelectPopWith 0
+#endif
+
/*
** Return code from the parse-tree walking primitives and their
** callbacks.
@@ -19285,20 +19491,56 @@ SQLITE_PRIVATE void sqlcipher_sqlite3SelectWalkAssert2(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.
+** A single common table expression
+*/
+struct Cte {
+ char *zName; /* Name of this CTE */
+ ExprList *pCols; /* List of explicit column names, or NULL */
+ Select *pSelect; /* The definition of this CTE */
+ const char *zCteErr; /* Error message for circular references */
+ CteUse *pUse; /* Usage information for this CTE */
+ u8 eM10d; /* The MATERIALIZED flag */
+};
+
+/*
+** Allowed values for the materialized flag (eM10d):
+*/
+#define M10d_Yes 0 /* AS MATERIALIZED */
+#define M10d_Any 1 /* Not specified. Query planner's choice */
+#define M10d_No 2 /* AS NOT MATERIALIZED */
+
+/*
+** An instance of the With object represents a WITH clause containing
+** one or more CTEs (common table expressions).
*/
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 *zCteErr; /* Error message for circular references */
- } a[1];
+ int nCte; /* Number of CTEs in the WITH clause */
+ int bView; /* Belongs to the outermost Select of a view */
+ With *pOuter; /* Containing WITH clause, or NULL */
+ Cte a[1]; /* For each CTE in the WITH clause.... */
+};
+
+/*
+** The Cte object is not guaranteed to persist for the entire duration
+** of code generation. (The query flattener or other parser tree
+** edits might delete it.) The following object records information
+** about each Common Table Expression that must be preserved for the
+** duration of the parse.
+**
+** The CteUse objects are freed using sqlcipher_sqlite3ParserAddCleanup() rather
+** than sqlcipher_sqlite3SelectDelete(), which is what enables them to persist
+** until the end of code generation.
+*/
+struct CteUse {
+ int nUse; /* Number of users of this CTE */
+ int addrM9e; /* Start of subroutine to compute materialization */
+ int regRtn; /* Return address register for addrM9e subroutine */
+ int iCur; /* Ephemeral table holding the materialization */
+ LogEst nRowEst; /* Estimated number of rows in the table */
+ u8 eM10d; /* The MATERIALIZED flag */
};
+
#ifdef SQLITE_DEBUG
/*
** An instance of the TreeView object is used for printing the content of
@@ -19348,7 +19590,7 @@ struct Window {
Window **ppThis; /* Pointer to this object in Select.pWin list */
Window *pNextWin; /* Next window function belonging to this SELECT */
Expr *pFilter; /* The FILTER expression */
- FuncDef *pFunc; /* The function */
+ FuncDef *pWFunc; /* The function */
int iEphCsr; /* Partition buffer or Peer buffer */
int regAccum; /* Accumulator */
int regResult; /* Interim result */
@@ -19372,11 +19614,10 @@ SQLITE_PRIVATE void sqlcipher_sqlite3WindowListDelete(sqlcipher_sqlite3 *db, Win
SQLITE_PRIVATE Window *sqlcipher_sqlite3WindowAlloc(Parse*, int, int, Expr*, int , Expr*, u8);
SQLITE_PRIVATE void sqlcipher_sqlite3WindowAttach(Parse*, Expr*, Window*);
SQLITE_PRIVATE void sqlcipher_sqlite3WindowLink(Select *pSel, Window *pWin);
-SQLITE_PRIVATE int sqlcipher_sqlite3WindowCompare(Parse*, Window*, Window*, int);
+SQLITE_PRIVATE int sqlcipher_sqlite3WindowCompare(const Parse*, const Window*, const Window*, int);
SQLITE_PRIVATE void sqlcipher_sqlite3WindowCodeInit(Parse*, Select*);
SQLITE_PRIVATE void sqlcipher_sqlite3WindowCodeStep(Parse*, Select*, WhereInfo*, int, int);
SQLITE_PRIVATE int sqlcipher_sqlite3WindowRewrite(Parse*, Select*);
-SQLITE_PRIVATE int sqlcipher_sqlite3ExpandSubquery(Parse*, struct SrcList_item*);
SQLITE_PRIVATE void sqlcipher_sqlite3WindowUpdate(Parse*, Window*, Window*, FuncDef*);
SQLITE_PRIVATE Window *sqlcipher_sqlite3WindowDup(sqlcipher_sqlite3 *db, Expr *pOwner, Window *p);
SQLITE_PRIVATE Window *sqlcipher_sqlite3WindowListDup(sqlcipher_sqlite3 *db, Window *p);
@@ -19505,8 +19746,8 @@ SQLITE_PRIVATE void *sqlcipher_sqlite3DbReallocOrFree(sqlcipher_sqlite3 *, void
SQLITE_PRIVATE void *sqlcipher_sqlite3DbRealloc(sqlcipher_sqlite3 *, void *, u64);
SQLITE_PRIVATE void sqlcipher_sqlite3DbFree(sqlcipher_sqlite3*, void*);
SQLITE_PRIVATE void sqlcipher_sqlite3DbFreeNN(sqlcipher_sqlite3*, void*);
-SQLITE_PRIVATE int sqlcipher_sqlite3MallocSize(void*);
-SQLITE_PRIVATE int sqlcipher_sqlite3DbMallocSize(sqlcipher_sqlite3*, void*);
+SQLITE_PRIVATE int sqlcipher_sqlite3MallocSize(const void*);
+SQLITE_PRIVATE int sqlcipher_sqlite3DbMallocSize(sqlcipher_sqlite3*, const void*);
SQLITE_PRIVATE void *sqlcipher_sqlite3PageMalloc(int);
SQLITE_PRIVATE void sqlcipher_sqlite3PageFree(void*);
SQLITE_PRIVATE void sqlcipher_sqlite3MemSetDefault(void);
@@ -19604,27 +19845,63 @@ SQLITE_PRIVATE void *sqlcipher_sqlite3TestTextToPtr(const char*);
#endif
#if defined(SQLITE_DEBUG)
+SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewLine(TreeView*, const char *zFormat, ...);
SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewExpr(TreeView*, const Expr*, u8);
SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewBareExprList(TreeView*, const ExprList*, const char*);
SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewExprList(TreeView*, const ExprList*, u8, const char*);
+SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewBareIdList(TreeView*, const IdList*, const char*);
+SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewIdList(TreeView*, const IdList*, u8, const char*);
+SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewColumnList(TreeView*, const Column*, int, u8);
SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewSrcList(TreeView*, const SrcList*);
SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewSelect(TreeView*, const Select*, u8);
SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewWith(TreeView*, const With*, u8);
+SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewUpsert(TreeView*, const Upsert*, u8);
+#if TREETRACE_ENABLED
+SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewDelete(const With*, const SrcList*, const Expr*,
+ const ExprList*,const Expr*, const Trigger*);
+SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewInsert(const With*, const SrcList*,
+ const IdList*, const Select*, const ExprList*,
+ int, const Upsert*, const Trigger*);
+SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewUpdate(const With*, const SrcList*, const ExprList*,
+ const Expr*, int, const ExprList*, const Expr*,
+ const Upsert*, const Trigger*);
+#endif
+#ifndef SQLITE_OMIT_TRIGGER
+SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewTriggerStep(TreeView*, const TriggerStep*, u8, u8);
+SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewTrigger(TreeView*, const Trigger*, u8, u8);
+#endif
#ifndef SQLITE_OMIT_WINDOWFUNC
SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewWindow(TreeView*, const Window*, u8);
SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewWinFunc(TreeView*, const Window*, u8);
#endif
+SQLITE_PRIVATE void sqlcipher_sqlite3ShowExpr(const Expr*);
+SQLITE_PRIVATE void sqlcipher_sqlite3ShowExprList(const ExprList*);
+SQLITE_PRIVATE void sqlcipher_sqlite3ShowIdList(const IdList*);
+SQLITE_PRIVATE void sqlcipher_sqlite3ShowSrcList(const SrcList*);
+SQLITE_PRIVATE void sqlcipher_sqlite3ShowSelect(const Select*);
+SQLITE_PRIVATE void sqlcipher_sqlite3ShowWith(const With*);
+SQLITE_PRIVATE void sqlcipher_sqlite3ShowUpsert(const Upsert*);
+#ifndef SQLITE_OMIT_TRIGGER
+SQLITE_PRIVATE void sqlcipher_sqlite3ShowTriggerStep(const TriggerStep*);
+SQLITE_PRIVATE void sqlcipher_sqlite3ShowTriggerStepList(const TriggerStep*);
+SQLITE_PRIVATE void sqlcipher_sqlite3ShowTrigger(const Trigger*);
+SQLITE_PRIVATE void sqlcipher_sqlite3ShowTriggerList(const Trigger*);
+#endif
+#ifndef SQLITE_OMIT_WINDOWFUNC
+SQLITE_PRIVATE void sqlcipher_sqlite3ShowWindow(const Window*);
+SQLITE_PRIVATE void sqlcipher_sqlite3ShowWinFunc(const Window*);
+#endif
#endif
-
SQLITE_PRIVATE void sqlcipher_sqlite3SetString(char **, sqlcipher_sqlite3*, const char*);
SQLITE_PRIVATE void sqlcipher_sqlite3ErrorMsg(Parse*, const char*, ...);
SQLITE_PRIVATE int sqlcipher_sqlite3ErrorToParser(sqlcipher_sqlite3*,int);
SQLITE_PRIVATE void sqlcipher_sqlite3Dequote(char*);
SQLITE_PRIVATE void sqlcipher_sqlite3DequoteExpr(Expr*);
+SQLITE_PRIVATE void sqlcipher_sqlite3DequoteToken(Token*);
SQLITE_PRIVATE void sqlcipher_sqlite3TokenInit(Token*,char*);
SQLITE_PRIVATE int sqlcipher_sqlite3KeywordCode(const unsigned char*, int);
-SQLITE_PRIVATE int sqlcipher_sqlite3RunParser(Parse*, const char*, char **);
+SQLITE_PRIVATE int sqlcipher_sqlite3RunParser(Parse*, const char*);
SQLITE_PRIVATE void sqlcipher_sqlite3FinishCoding(Parse*);
SQLITE_PRIVATE int sqlcipher_sqlite3GetTempReg(Parse*);
SQLITE_PRIVATE void sqlcipher_sqlite3ReleaseTempReg(Parse*,int);
@@ -19641,15 +19918,17 @@ SQLITE_PRIVATE Expr *sqlcipher_sqlite3PExpr(Parse*, int, Expr*, Expr*);
SQLITE_PRIVATE void sqlcipher_sqlite3PExprAddSelect(Parse*, Expr*, Select*);
SQLITE_PRIVATE Expr *sqlcipher_sqlite3ExprAnd(Parse*,Expr*, Expr*);
SQLITE_PRIVATE Expr *sqlcipher_sqlite3ExprSimplifiedAndOr(Expr*);
-SQLITE_PRIVATE Expr *sqlcipher_sqlite3ExprFunction(Parse*,ExprList*, Token*, int);
-SQLITE_PRIVATE void sqlcipher_sqlite3ExprFunctionUsable(Parse*,Expr*,FuncDef*);
+SQLITE_PRIVATE Expr *sqlcipher_sqlite3ExprFunction(Parse*,ExprList*, const Token*, int);
+SQLITE_PRIVATE void sqlcipher_sqlite3ExprFunctionUsable(Parse*,const Expr*,const FuncDef*);
SQLITE_PRIVATE void sqlcipher_sqlite3ExprAssignVarNumber(Parse*, Expr*, u32);
SQLITE_PRIVATE void sqlcipher_sqlite3ExprDelete(sqlcipher_sqlite3*, Expr*);
+SQLITE_PRIVATE void sqlcipher_sqlite3ExprDeferredDelete(Parse*, Expr*);
SQLITE_PRIVATE void sqlcipher_sqlite3ExprUnmapAndDelete(Parse*, Expr*);
SQLITE_PRIVATE ExprList *sqlcipher_sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
SQLITE_PRIVATE ExprList *sqlcipher_sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*);
+SQLITE_PRIVATE Select *sqlcipher_sqlite3ExprListToValues(Parse*, int, ExprList*);
SQLITE_PRIVATE void sqlcipher_sqlite3ExprListSetSortOrder(ExprList*,int,int);
-SQLITE_PRIVATE void sqlcipher_sqlite3ExprListSetName(Parse*,ExprList*,Token*,int);
+SQLITE_PRIVATE void sqlcipher_sqlite3ExprListSetName(Parse*,ExprList*,const Token*,int);
SQLITE_PRIVATE void sqlcipher_sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*);
SQLITE_PRIVATE void sqlcipher_sqlite3ExprListDelete(sqlcipher_sqlite3*, ExprList*);
SQLITE_PRIVATE u32 sqlcipher_sqlite3ExprListFlags(const ExprList*);
@@ -19665,7 +19944,12 @@ SQLITE_PRIVATE void sqlcipher_sqlite3ResetAllSchemasOfConnection(sqlcipher_sqlit
SQLITE_PRIVATE void sqlcipher_sqlite3ResetOneSchema(sqlcipher_sqlite3*,int);
SQLITE_PRIVATE void sqlcipher_sqlite3CollapseDatabaseArray(sqlcipher_sqlite3*);
SQLITE_PRIVATE void sqlcipher_sqlite3CommitInternalChanges(sqlcipher_sqlite3*);
+SQLITE_PRIVATE void sqlcipher_sqlite3ColumnSetExpr(Parse*,Table*,Column*,Expr*);
+SQLITE_PRIVATE Expr *sqlcipher_sqlite3ColumnExpr(Table*,Column*);
+SQLITE_PRIVATE void sqlcipher_sqlite3ColumnSetColl(sqlcipher_sqlite3*,Column*,const char*zColl);
+SQLITE_PRIVATE const char *sqlcipher_sqlite3ColumnColl(Column*);
SQLITE_PRIVATE void sqlcipher_sqlite3DeleteColumnNames(sqlcipher_sqlite3*,Table*);
+SQLITE_PRIVATE void sqlcipher_sqlite3GenerateColumnNames(Parse *pParse, Select *pSelect);
SQLITE_PRIVATE int sqlcipher_sqlite3ColumnsFromExprList(Parse*,ExprList*,i16*,Column**);
SQLITE_PRIVATE void sqlcipher_sqlite3SelectAddColumnTypeAndCollation(Parse*,Table*,Select*,char);
SQLITE_PRIVATE Table *sqlcipher_sqlite3ResultSetOfSelect(Parse*,Select*,char);
@@ -19685,14 +19969,15 @@ SQLITE_PRIVATE void sqlcipher_sqlite3ColumnPropertiesFromName(Table*, Column*)
#else
# define sqlcipher_sqlite3ColumnPropertiesFromName(T,C) /* no-op */
#endif
-SQLITE_PRIVATE void sqlcipher_sqlite3AddColumn(Parse*,Token*,Token*);
+SQLITE_PRIVATE void sqlcipher_sqlite3AddColumn(Parse*,Token,Token);
SQLITE_PRIVATE void sqlcipher_sqlite3AddNotNull(Parse*, int);
SQLITE_PRIVATE void sqlcipher_sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int);
SQLITE_PRIVATE void sqlcipher_sqlite3AddCheckConstraint(Parse*, Expr*, const char*, const char*);
SQLITE_PRIVATE void sqlcipher_sqlite3AddDefaultValue(Parse*,Expr*,const char*,const char*);
SQLITE_PRIVATE void sqlcipher_sqlite3AddCollateType(Parse*, Token*);
SQLITE_PRIVATE void sqlcipher_sqlite3AddGenerated(Parse*,Expr*,Token*);
-SQLITE_PRIVATE void sqlcipher_sqlite3EndTable(Parse*,Token*,Token*,u8,Select*);
+SQLITE_PRIVATE void sqlcipher_sqlite3EndTable(Parse*,Token*,Token*,u32,Select*);
+SQLITE_PRIVATE void sqlcipher_sqlite3AddReturning(Parse*,ExprList*);
SQLITE_PRIVATE int sqlcipher_sqlite3ParseUri(const char*,const char*,unsigned int*,
sqlcipher_sqlite3_vfs**,char**,char **);
/* BEGIN SQLCIPHER */
@@ -19761,13 +20046,14 @@ SQLITE_PRIVATE SrcList *sqlcipher_sqlite3SrcListEnlarge(Parse*, SrcList*, int, i
SQLITE_PRIVATE SrcList *sqlcipher_sqlite3SrcListAppendList(Parse *pParse, SrcList *p1, SrcList *p2);
SQLITE_PRIVATE SrcList *sqlcipher_sqlite3SrcListAppend(Parse*, SrcList*, Token*, Token*);
SQLITE_PRIVATE SrcList *sqlcipher_sqlite3SrcListAppendFromTerm(Parse*, SrcList*, Token*, Token*,
- Token*, Select*, Expr*, IdList*);
+ Token*, Select*, OnOrUsing*);
SQLITE_PRIVATE void sqlcipher_sqlite3SrcListIndexedBy(Parse *, SrcList *, Token *);
SQLITE_PRIVATE void sqlcipher_sqlite3SrcListFuncArgs(Parse*, SrcList*, ExprList*);
-SQLITE_PRIVATE int sqlcipher_sqlite3IndexedByLookup(Parse *, struct SrcList_item *);
-SQLITE_PRIVATE void sqlcipher_sqlite3SrcListShiftJoinType(SrcList*);
+SQLITE_PRIVATE int sqlcipher_sqlite3IndexedByLookup(Parse *, SrcItem *);
+SQLITE_PRIVATE void sqlcipher_sqlite3SrcListShiftJoinType(Parse*,SrcList*);
SQLITE_PRIVATE void sqlcipher_sqlite3SrcListAssignCursors(Parse*, SrcList*);
SQLITE_PRIVATE void sqlcipher_sqlite3IdListDelete(sqlcipher_sqlite3*, IdList*);
+SQLITE_PRIVATE void sqlcipher_sqlite3ClearOnOrUsing(sqlcipher_sqlite3*, OnOrUsing*);
SQLITE_PRIVATE void sqlcipher_sqlite3SrcListDelete(sqlcipher_sqlite3*, SrcList*);
SQLITE_PRIVATE Index *sqlcipher_sqlite3AllocateIndexObject(sqlcipher_sqlite3*,i16,int,char**);
SQLITE_PRIVATE void sqlcipher_sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*,
@@ -19783,15 +20069,18 @@ SQLITE_PRIVATE void sqlcipher_sqlite3OpenTable(Parse*, int iCur, int iDb, Table*
#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
SQLITE_PRIVATE Expr *sqlcipher_sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,char*);
#endif
+SQLITE_PRIVATE void sqlcipher_sqlite3CodeChangeCount(Vdbe*,int,const char*);
SQLITE_PRIVATE void sqlcipher_sqlite3DeleteFrom(Parse*, SrcList*, Expr*, ExprList*, Expr*);
SQLITE_PRIVATE void sqlcipher_sqlite3Update(Parse*, SrcList*, ExprList*,Expr*,int,ExprList*,Expr*,
Upsert*);
-SQLITE_PRIVATE WhereInfo *sqlcipher_sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,ExprList*,u16,int);
+SQLITE_PRIVATE WhereInfo *sqlcipher_sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,
+ ExprList*,Select*,u16,int);
SQLITE_PRIVATE void sqlcipher_sqlite3WhereEnd(WhereInfo*);
SQLITE_PRIVATE LogEst sqlcipher_sqlite3WhereOutputRowCount(WhereInfo*);
SQLITE_PRIVATE int sqlcipher_sqlite3WhereIsDistinct(WhereInfo*);
SQLITE_PRIVATE int sqlcipher_sqlite3WhereIsOrdered(WhereInfo*);
SQLITE_PRIVATE int sqlcipher_sqlite3WhereOrderByLimitOptLabel(WhereInfo*);
+SQLITE_PRIVATE void sqlcipher_sqlite3WhereMinMaxOptEarlyOut(Vdbe*,WhereInfo*);
SQLITE_PRIVATE int sqlcipher_sqlite3WhereIsSorted(WhereInfo*);
SQLITE_PRIVATE int sqlcipher_sqlite3WhereContinueLabel(WhereInfo*);
SQLITE_PRIVATE int sqlcipher_sqlite3WhereBreakLabel(WhereInfo*);
@@ -19806,7 +20095,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int
SQLITE_PRIVATE void sqlcipher_sqlite3ExprCodeMove(Parse*, int, int, int);
SQLITE_PRIVATE void sqlcipher_sqlite3ExprCode(Parse*, Expr*, int);
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
-SQLITE_PRIVATE void sqlcipher_sqlite3ExprCodeGeneratedColumn(Parse*, Column*, int);
+SQLITE_PRIVATE void sqlcipher_sqlite3ExprCodeGeneratedColumn(Parse*, Table*, Column*, int);
#endif
SQLITE_PRIVATE void sqlcipher_sqlite3ExprCodeCopy(Parse*, Expr*, int);
SQLITE_PRIVATE void sqlcipher_sqlite3ExprCodeFactorable(Parse*, Expr*, int);
@@ -19825,23 +20114,24 @@ SQLITE_PRIVATE Table *sqlcipher_sqlite3FindTable(sqlcipher_sqlite3*,const char*,
#define LOCATE_VIEW 0x01
#define LOCATE_NOERR 0x02
SQLITE_PRIVATE Table *sqlcipher_sqlite3LocateTable(Parse*,u32 flags,const char*, const char*);
-SQLITE_PRIVATE Table *sqlcipher_sqlite3LocateTableItem(Parse*,u32 flags,struct SrcList_item *);
+SQLITE_PRIVATE const char *sqlcipher_sqlite3PreferredTableName(const char*);
+SQLITE_PRIVATE Table *sqlcipher_sqlite3LocateTableItem(Parse*,u32 flags,SrcItem *);
SQLITE_PRIVATE Index *sqlcipher_sqlite3FindIndex(sqlcipher_sqlite3*,const char*, const char*);
SQLITE_PRIVATE void sqlcipher_sqlite3UnlinkAndDeleteTable(sqlcipher_sqlite3*,int,const char*);
SQLITE_PRIVATE void sqlcipher_sqlite3UnlinkAndDeleteIndex(sqlcipher_sqlite3*,int,const char*);
SQLITE_PRIVATE void sqlcipher_sqlite3Vacuum(Parse*,Token*,Expr*);
SQLITE_PRIVATE int sqlcipher_sqlite3RunVacuum(char**, sqlcipher_sqlite3*, int, sqlcipher_sqlite3_value*);
-SQLITE_PRIVATE char *sqlcipher_sqlite3NameFromToken(sqlcipher_sqlite3*, Token*);
-SQLITE_PRIVATE int sqlcipher_sqlite3ExprCompare(Parse*,Expr*, Expr*, int);
-SQLITE_PRIVATE int sqlcipher_sqlite3ExprCompareSkip(Expr*, Expr*, int);
-SQLITE_PRIVATE int sqlcipher_sqlite3ExprListCompare(ExprList*, ExprList*, int);
-SQLITE_PRIVATE int sqlcipher_sqlite3ExprImpliesExpr(Parse*,Expr*, Expr*, int);
+SQLITE_PRIVATE char *sqlcipher_sqlite3NameFromToken(sqlcipher_sqlite3*, const Token*);
+SQLITE_PRIVATE int sqlcipher_sqlite3ExprCompare(const Parse*,const Expr*,const Expr*, int);
+SQLITE_PRIVATE int sqlcipher_sqlite3ExprCompareSkip(Expr*,Expr*,int);
+SQLITE_PRIVATE int sqlcipher_sqlite3ExprListCompare(const ExprList*,const ExprList*, int);
+SQLITE_PRIVATE int sqlcipher_sqlite3ExprImpliesExpr(const Parse*,const Expr*,const Expr*, int);
SQLITE_PRIVATE int sqlcipher_sqlite3ExprImpliesNonNullRow(Expr*,int);
SQLITE_PRIVATE void sqlcipher_sqlite3AggInfoPersistWalkerInit(Walker*,Parse*);
SQLITE_PRIVATE void sqlcipher_sqlite3ExprAnalyzeAggregates(NameContext*, Expr*);
SQLITE_PRIVATE void sqlcipher_sqlite3ExprAnalyzeAggList(NameContext*,ExprList*);
SQLITE_PRIVATE int sqlcipher_sqlite3ExprCoveredByIndex(Expr*, int iCur, Index *pIdx);
-SQLITE_PRIVATE int sqlcipher_sqlite3FunctionUsesThisSrc(Expr*, SrcList*);
+SQLITE_PRIVATE int sqlcipher_sqlite3ReferencesSrcList(Parse*, Expr*, SrcList*);
SQLITE_PRIVATE Vdbe *sqlcipher_sqlite3GetVdbe(Parse*);
#ifndef SQLITE_UNTESTABLE
SQLITE_PRIVATE void sqlcipher_sqlite3PrngSaveState(void);
@@ -19863,10 +20153,11 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ExprIsConstantNotJoin(Expr*);
SQLITE_PRIVATE int sqlcipher_sqlite3ExprIsConstantOrFunction(Expr*, u8);
SQLITE_PRIVATE int sqlcipher_sqlite3ExprIsConstantOrGroupBy(Parse*, Expr*, ExprList*);
SQLITE_PRIVATE int sqlcipher_sqlite3ExprIsTableConstant(Expr*,int);
+SQLITE_PRIVATE int sqlcipher_sqlite3ExprIsTableConstraint(Expr*,const SrcItem*);
#ifdef SQLITE_ENABLE_CURSOR_HINTS
SQLITE_PRIVATE int sqlcipher_sqlite3ExprContainsSubquery(Expr*);
#endif
-SQLITE_PRIVATE int sqlcipher_sqlite3ExprIsInteger(Expr*, int*);
+SQLITE_PRIVATE int sqlcipher_sqlite3ExprIsInteger(const Expr*, int*);
SQLITE_PRIVATE int sqlcipher_sqlite3ExprCanBeNull(const Expr*);
SQLITE_PRIVATE int sqlcipher_sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
SQLITE_PRIVATE int sqlcipher_sqlite3IsRowid(const char*);
@@ -19891,20 +20182,26 @@ SQLITE_PRIVATE void sqlcipher_sqlite3MayAbort(Parse*);
SQLITE_PRIVATE void sqlcipher_sqlite3HaltConstraint(Parse*, int, int, char*, i8, u8);
SQLITE_PRIVATE void sqlcipher_sqlite3UniqueConstraint(Parse*, int, Index*);
SQLITE_PRIVATE void sqlcipher_sqlite3RowidConstraint(Parse*, int, Table*);
-SQLITE_PRIVATE Expr *sqlcipher_sqlite3ExprDup(sqlcipher_sqlite3*,Expr*,int);
-SQLITE_PRIVATE ExprList *sqlcipher_sqlite3ExprListDup(sqlcipher_sqlite3*,ExprList*,int);
-SQLITE_PRIVATE SrcList *sqlcipher_sqlite3SrcListDup(sqlcipher_sqlite3*,SrcList*,int);
-SQLITE_PRIVATE IdList *sqlcipher_sqlite3IdListDup(sqlcipher_sqlite3*,IdList*);
-SQLITE_PRIVATE Select *sqlcipher_sqlite3SelectDup(sqlcipher_sqlite3*,Select*,int);
+SQLITE_PRIVATE Expr *sqlcipher_sqlite3ExprDup(sqlcipher_sqlite3*,const Expr*,int);
+SQLITE_PRIVATE ExprList *sqlcipher_sqlite3ExprListDup(sqlcipher_sqlite3*,const ExprList*,int);
+SQLITE_PRIVATE SrcList *sqlcipher_sqlite3SrcListDup(sqlcipher_sqlite3*,const SrcList*,int);
+SQLITE_PRIVATE IdList *sqlcipher_sqlite3IdListDup(sqlcipher_sqlite3*,const IdList*);
+SQLITE_PRIVATE Select *sqlcipher_sqlite3SelectDup(sqlcipher_sqlite3*,const Select*,int);
SQLITE_PRIVATE FuncDef *sqlcipher_sqlite3FunctionSearch(int,const char*);
SQLITE_PRIVATE void sqlcipher_sqlite3InsertBuiltinFuncs(FuncDef*,int);
SQLITE_PRIVATE FuncDef *sqlcipher_sqlite3FindFunction(sqlcipher_sqlite3*,const char*,int,u8,u8);
+SQLITE_PRIVATE void sqlcipher_sqlite3QuoteValue(StrAccum*,sqlcipher_sqlite3_value*);
SQLITE_PRIVATE void sqlcipher_sqlite3RegisterBuiltinFunctions(void);
SQLITE_PRIVATE void sqlcipher_sqlite3RegisterDateTimeFunctions(void);
+SQLITE_PRIVATE void sqlcipher_sqlite3RegisterJsonFunctions(void);
SQLITE_PRIVATE void sqlcipher_sqlite3RegisterPerConnectionBuiltinFunctions(sqlcipher_sqlite3*);
+#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_JSON)
+SQLITE_PRIVATE int sqlcipher_sqlite3JsonTableFunctions(sqlcipher_sqlite3*);
+#endif
SQLITE_PRIVATE int sqlcipher_sqlite3SafetyCheckOk(sqlcipher_sqlite3*);
SQLITE_PRIVATE int sqlcipher_sqlite3SafetyCheckSickOrOk(sqlcipher_sqlite3*);
SQLITE_PRIVATE void sqlcipher_sqlite3ChangeCookie(Parse*, int);
+SQLITE_PRIVATE With *sqlcipher_sqlite3WithDup(sqlcipher_sqlite3 *db, With *p);
#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
SQLITE_PRIVATE void sqlcipher_sqlite3MaterializeView(Parse*, Table*, Expr*, ExprList*,Expr*,int);
@@ -19953,7 +20250,9 @@ SQLITE_PRIVATE SrcList *sqlcipher_sqlite3TriggerStepSrc(Parse*, TriggerStep*);
#endif
SQLITE_PRIVATE int sqlcipher_sqlite3JoinType(Parse*, Token*, Token*, Token*);
-SQLITE_PRIVATE void sqlcipher_sqlite3SetJoinExpr(Expr*,int);
+SQLITE_PRIVATE int sqlcipher_sqlite3ColumnIndex(Table *pTab, const char *zCol);
+SQLITE_PRIVATE void sqlcipher_sqlite3SrcItemColumnUsed(SrcItem*,int);
+SQLITE_PRIVATE void sqlcipher_sqlite3SetJoinExpr(Expr*,int,u32);
SQLITE_PRIVATE void sqlcipher_sqlite3CreateForeignKey(Parse*, ExprList*, Token*, ExprList*, int);
SQLITE_PRIVATE void sqlcipher_sqlite3DeferForeignKey(Parse*, int);
#ifndef SQLITE_OMIT_AUTHORIZATION
@@ -19975,7 +20274,6 @@ SQLITE_PRIVATE void sqlcipher_sqlite3FixInit(DbFixer*, Parse*, int, const char*,
SQLITE_PRIVATE int sqlcipher_sqlite3FixSrcList(DbFixer*, SrcList*);
SQLITE_PRIVATE int sqlcipher_sqlite3FixSelect(DbFixer*, Select*);
SQLITE_PRIVATE int sqlcipher_sqlite3FixExpr(DbFixer*, Expr*);
-SQLITE_PRIVATE int sqlcipher_sqlite3FixExprList(DbFixer*, ExprList*);
SQLITE_PRIVATE int sqlcipher_sqlite3FixTriggerStep(DbFixer*, TriggerStep*);
SQLITE_PRIVATE int sqlcipher_sqlite3RealSameAsInt(double,sqlcipher_sqlite3_int64);
SQLITE_PRIVATE void sqlcipher_sqlite3Int64ToText(i64,char*);
@@ -19990,14 +20288,8 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Utf8CharLen(const char *pData, int nByte);
SQLITE_PRIVATE u32 sqlcipher_sqlite3Utf8Read(const u8**);
SQLITE_PRIVATE LogEst sqlcipher_sqlite3LogEst(u64);
SQLITE_PRIVATE LogEst sqlcipher_sqlite3LogEstAdd(LogEst,LogEst);
-#ifndef SQLITE_OMIT_VIRTUALTABLE
SQLITE_PRIVATE LogEst sqlcipher_sqlite3LogEstFromDouble(double);
-#endif
-#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || \
- defined(SQLITE_ENABLE_STAT4) || \
- defined(SQLITE_EXPLAIN_ESTIMATED_ROWS)
SQLITE_PRIVATE u64 sqlcipher_sqlite3LogEstToInt(LogEst);
-#endif
SQLITE_PRIVATE VList *sqlcipher_sqlite3VListAdd(sqlcipher_sqlite3*,VList*,const char*,int,int);
SQLITE_PRIVATE const char *sqlcipher_sqlite3VListNumToName(VList*,int);
SQLITE_PRIVATE int sqlcipher_sqlite3VListNameToNum(VList*,const char*,int);
@@ -20032,12 +20324,13 @@ SQLITE_PRIVATE const char *sqlcipher_sqlite3IndexAffinityStr(sqlcipher_sqlite3*,
SQLITE_PRIVATE void sqlcipher_sqlite3TableAffinity(Vdbe*, Table*, int);
SQLITE_PRIVATE char sqlcipher_sqlite3CompareAffinity(const Expr *pExpr, char aff2);
SQLITE_PRIVATE int sqlcipher_sqlite3IndexAffinityOk(const Expr *pExpr, char idx_affinity);
-SQLITE_PRIVATE char sqlcipher_sqlite3TableColumnAffinity(Table*,int);
+SQLITE_PRIVATE char sqlcipher_sqlite3TableColumnAffinity(const Table*,int);
SQLITE_PRIVATE char sqlcipher_sqlite3ExprAffinity(const Expr *pExpr);
SQLITE_PRIVATE int sqlcipher_sqlite3Atoi64(const char*, i64*, int, u8);
SQLITE_PRIVATE int sqlcipher_sqlite3DecOrHexToI64(const char*, i64*);
SQLITE_PRIVATE void sqlcipher_sqlite3ErrorWithMsg(sqlcipher_sqlite3*, int, const char*,...);
SQLITE_PRIVATE void sqlcipher_sqlite3Error(sqlcipher_sqlite3*,int);
+SQLITE_PRIVATE void sqlcipher_sqlite3ErrorClear(sqlcipher_sqlite3*);
SQLITE_PRIVATE void sqlcipher_sqlite3SystemError(sqlcipher_sqlite3*,int);
SQLITE_PRIVATE void *sqlcipher_sqlite3HexToBlob(sqlcipher_sqlite3*, const char *z, int n);
SQLITE_PRIVATE u8 sqlcipher_sqlite3HexToInt(int h);
@@ -20047,7 +20340,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3TwoPartName(Parse *, Token *, Token *, Token
SQLITE_PRIVATE const char *sqlcipher_sqlite3ErrName(int);
#endif
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
SQLITE_PRIVATE int sqlcipher_sqlite3MemdbInit(void);
#endif
@@ -20060,14 +20353,14 @@ SQLITE_PRIVATE void sqlcipher_sqlite3SetTextEncoding(sqlcipher_sqlite3 *db, u8);
SQLITE_PRIVATE CollSeq *sqlcipher_sqlite3ExprCollSeq(Parse *pParse, const Expr *pExpr);
SQLITE_PRIVATE CollSeq *sqlcipher_sqlite3ExprNNCollSeq(Parse *pParse, const Expr *pExpr);
SQLITE_PRIVATE int sqlcipher_sqlite3ExprCollSeqMatch(Parse*,const Expr*,const Expr*);
-SQLITE_PRIVATE Expr *sqlcipher_sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*, int);
-SQLITE_PRIVATE Expr *sqlcipher_sqlite3ExprAddCollateString(Parse*,Expr*,const char*);
+SQLITE_PRIVATE Expr *sqlcipher_sqlite3ExprAddCollateToken(const Parse *pParse, Expr*, const Token*, int);
+SQLITE_PRIVATE Expr *sqlcipher_sqlite3ExprAddCollateString(const Parse*,Expr*,const char*);
SQLITE_PRIVATE Expr *sqlcipher_sqlite3ExprSkipCollate(Expr*);
SQLITE_PRIVATE Expr *sqlcipher_sqlite3ExprSkipCollateAndLikely(Expr*);
SQLITE_PRIVATE int sqlcipher_sqlite3CheckCollSeq(Parse *, CollSeq *);
SQLITE_PRIVATE int sqlcipher_sqlite3WritableSchema(sqlcipher_sqlite3*);
SQLITE_PRIVATE int sqlcipher_sqlite3CheckObjectName(Parse*, const char*,const char*,const char*);
-SQLITE_PRIVATE void sqlcipher_sqlite3VdbeSetChanges(sqlcipher_sqlite3 *, int);
+SQLITE_PRIVATE void sqlcipher_sqlite3VdbeSetChanges(sqlcipher_sqlite3 *, i64);
SQLITE_PRIVATE int sqlcipher_sqlite3AddInt64(i64*,i64);
SQLITE_PRIVATE int sqlcipher_sqlite3SubInt64(i64*,i64);
SQLITE_PRIVATE int sqlcipher_sqlite3MulInt64(i64*,i64);
@@ -20092,16 +20385,22 @@ SQLITE_PRIVATE sqlcipher_sqlite3_value *sqlcipher_sqlite3ValueNew(sqlcipher_sqli
#ifndef SQLITE_OMIT_UTF16
SQLITE_PRIVATE char *sqlcipher_sqlite3Utf16to8(sqlcipher_sqlite3 *, const void*, int, u8);
#endif
-SQLITE_PRIVATE int sqlcipher_sqlite3ValueFromExpr(sqlcipher_sqlite3 *, Expr *, u8, u8, sqlcipher_sqlite3_value **);
+SQLITE_PRIVATE int sqlcipher_sqlite3ValueFromExpr(sqlcipher_sqlite3 *, const Expr *, u8, u8, sqlcipher_sqlite3_value **);
SQLITE_PRIVATE void sqlcipher_sqlite3ValueApplyAffinity(sqlcipher_sqlite3_value *, u8, u8);
#ifndef SQLITE_AMALGAMATION
SQLITE_PRIVATE const unsigned char sqlcipher_sqlite3OpcodeProperty[];
SQLITE_PRIVATE const char sqlcipher_sqlite3StrBINARY[];
+SQLITE_PRIVATE const unsigned char sqlcipher_sqlite3StdTypeLen[];
+SQLITE_PRIVATE const char sqlcipher_sqlite3StdTypeAffinity[];
+SQLITE_PRIVATE const char sqlcipher_sqlite3StdTypeMap[];
+SQLITE_PRIVATE const char *sqlcipher_sqlite3StdType[];
SQLITE_PRIVATE const unsigned char sqlcipher_sqlite3UpperToLower[];
+SQLITE_PRIVATE const unsigned char *sqlcipher_sqlite3aLTb;
+SQLITE_PRIVATE const unsigned char *sqlcipher_sqlite3aEQb;
+SQLITE_PRIVATE const unsigned char *sqlcipher_sqlite3aGTb;
SQLITE_PRIVATE const unsigned char sqlcipher_sqlite3CtypeMap[];
SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlcipher_sqlite3Config;
SQLITE_PRIVATE FuncDefHash sqlcipher_sqlite3BuiltinFunctions;
-SQLITE_API extern u32 sqlcipher_sqlite3_unsupported_selecttrace;
#ifndef SQLITE_OMIT_WSD
SQLITE_PRIVATE int sqlcipher_sqlite3PendingByte;
#endif
@@ -20120,6 +20419,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3ExpirePreparedStatements(sqlcipher_sqlite3*
SQLITE_PRIVATE void sqlcipher_sqlite3CodeRhsOfIN(Parse*, Expr*, int);
SQLITE_PRIVATE int sqlcipher_sqlite3CodeSubselect(Parse*, Expr*);
SQLITE_PRIVATE void sqlcipher_sqlite3SelectPrep(Parse*, Select*, NameContext*);
+SQLITE_PRIVATE int sqlcipher_sqlite3ExpandSubquery(Parse*, SrcItem*);
SQLITE_PRIVATE void sqlcipher_sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p);
SQLITE_PRIVATE int sqlcipher_sqlite3MatchEName(
const struct ExprList_item*,
@@ -20137,8 +20437,9 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprLis
SQLITE_PRIVATE void sqlcipher_sqlite3ColumnDefault(Vdbe *, Table *, int, int);
SQLITE_PRIVATE void sqlcipher_sqlite3AlterFinishAddColumn(Parse *, Token *);
SQLITE_PRIVATE void sqlcipher_sqlite3AlterBeginAddColumn(Parse *, SrcList *);
-SQLITE_PRIVATE void *sqlcipher_sqlite3RenameTokenMap(Parse*, void*, Token*);
-SQLITE_PRIVATE void sqlcipher_sqlite3RenameTokenRemap(Parse*, void *pTo, void *pFrom);
+SQLITE_PRIVATE void sqlcipher_sqlite3AlterDropColumn(Parse*, SrcList*, const Token*);
+SQLITE_PRIVATE const void *sqlcipher_sqlite3RenameTokenMap(Parse*, const void*, const Token*);
+SQLITE_PRIVATE void sqlcipher_sqlite3RenameTokenRemap(Parse*, const void *pTo, const void *pFrom);
SQLITE_PRIVATE void sqlcipher_sqlite3RenameExprUnmap(Parse*, Expr*);
SQLITE_PRIVATE void sqlcipher_sqlite3RenameExprlistUnmap(Parse*, ExprList*);
SQLITE_PRIVATE CollSeq *sqlcipher_sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*);
@@ -20160,6 +20461,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3KeyInfoUnref(KeyInfo*);
SQLITE_PRIVATE KeyInfo *sqlcipher_sqlite3KeyInfoRef(KeyInfo*);
SQLITE_PRIVATE KeyInfo *sqlcipher_sqlite3KeyInfoOfIndex(Parse*, Index*);
SQLITE_PRIVATE KeyInfo *sqlcipher_sqlite3KeyInfoFromExprList(Parse*, ExprList*, int, int);
+SQLITE_PRIVATE const char *sqlcipher_sqlite3SelectOpName(int);
SQLITE_PRIVATE int sqlcipher_sqlite3HasExplicitNulls(Parse*, ExprList*);
#ifdef SQLITE_DEBUG
@@ -20174,15 +20476,20 @@ SQLITE_PRIVATE int sqlcipher_sqlite3CreateFunc(sqlcipher_sqlite3 *, const char *
FuncDestructor *pDestructor
);
SQLITE_PRIVATE void sqlcipher_sqlite3NoopDestructor(void*);
-SQLITE_PRIVATE void sqlcipher_sqlite3OomFault(sqlcipher_sqlite3*);
+SQLITE_PRIVATE void *sqlcipher_sqlite3OomFault(sqlcipher_sqlite3*);
SQLITE_PRIVATE void sqlcipher_sqlite3OomClear(sqlcipher_sqlite3*);
SQLITE_PRIVATE int sqlcipher_sqlite3ApiExit(sqlcipher_sqlite3 *db, int);
SQLITE_PRIVATE int sqlcipher_sqlite3OpenTempDatabase(Parse *);
SQLITE_PRIVATE void sqlcipher_sqlite3StrAccumInit(StrAccum*, sqlcipher_sqlite3*, char*, int, int);
+SQLITE_PRIVATE int sqlcipher_sqlite3StrAccumEnlarge(StrAccum*, int);
SQLITE_PRIVATE char *sqlcipher_sqlite3StrAccumFinish(StrAccum*);
+SQLITE_PRIVATE void sqlcipher_sqlite3StrAccumSetError(StrAccum*, u8);
+SQLITE_PRIVATE void sqlcipher_sqlite3ResultStrAccum(sqlcipher_sqlite3_context*,StrAccum*);
SQLITE_PRIVATE void sqlcipher_sqlite3SelectDestInit(SelectDest*,int,int);
SQLITE_PRIVATE Expr *sqlcipher_sqlite3CreateColumnExpr(sqlcipher_sqlite3 *, SrcList *, int, int);
+SQLITE_PRIVATE void sqlcipher_sqlite3RecordErrorByteOffset(sqlcipher_sqlite3*,const char*);
+SQLITE_PRIVATE void sqlcipher_sqlite3RecordErrorOffsetOfExpr(sqlcipher_sqlite3*,const Expr*);
SQLITE_PRIVATE void sqlcipher_sqlite3BackupRestart(sqlcipher_sqlite3_backup *);
SQLITE_PRIVATE void sqlcipher_sqlite3BackupUpdate(sqlcipher_sqlite3_backup *, Pgno, const u8 *);
@@ -20233,7 +20540,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Utf8To8(unsigned char*);
#endif
#ifdef SQLITE_OMIT_VIRTUALTABLE
-# define sqlcipher_sqlite3VtabClear(Y)
+# define sqlcipher_sqlite3VtabClear(D,T)
# define sqlcipher_sqlite3VtabSync(X,Y) SQLITE_OK
# define sqlcipher_sqlite3VtabRollback(X)
# define sqlcipher_sqlite3VtabCommit(X)
@@ -20270,9 +20577,11 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ReadOnlyShadowTables(sqlcipher_sqlite3 *db);
#ifndef SQLITE_OMIT_VIRTUALTABLE
SQLITE_PRIVATE int sqlcipher_sqlite3ShadowTableName(sqlcipher_sqlite3 *db, const char *zName);
SQLITE_PRIVATE int sqlcipher_sqlite3IsShadowTableOf(sqlcipher_sqlite3*,Table*,const char*);
+SQLITE_PRIVATE void sqlcipher_sqlite3MarkAllShadowTablesOf(sqlcipher_sqlite3*, Table*);
#else
# define sqlcipher_sqlite3ShadowTableName(A,B) 0
# define sqlcipher_sqlite3IsShadowTableOf(A,B,C) 0
+# define sqlcipher_sqlite3MarkAllShadowTablesOf(A,B)
#endif
SQLITE_PRIVATE int sqlcipher_sqlite3VtabEponymousTableInit(Parse*,Module*);
SQLITE_PRIVATE void sqlcipher_sqlite3VtabEponymousTableClear(sqlcipher_sqlite3*,Module*);
@@ -20285,11 +20594,18 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VtabCallCreate(sqlcipher_sqlite3*, int, cons
SQLITE_PRIVATE int sqlcipher_sqlite3VtabCallConnect(Parse*, Table*);
SQLITE_PRIVATE int sqlcipher_sqlite3VtabCallDestroy(sqlcipher_sqlite3*, int, const char *);
SQLITE_PRIVATE int sqlcipher_sqlite3VtabBegin(sqlcipher_sqlite3 *, VTable *);
+
SQLITE_PRIVATE FuncDef *sqlcipher_sqlite3VtabOverloadFunction(sqlcipher_sqlite3 *,FuncDef*, int nArg, Expr*);
+#if (defined(SQLITE_ENABLE_DBPAGE_VTAB) || defined(SQLITE_TEST)) \
+ && !defined(SQLITE_OMIT_VIRTUALTABLE)
+SQLITE_PRIVATE void sqlcipher_sqlite3VtabUsesAllSchemas(sqlcipher_sqlite3_index_info*);
+#endif
SQLITE_PRIVATE sqlcipher_sqlite3_int64 sqlcipher_sqlite3StmtCurrentTime(sqlcipher_sqlite3_context*);
SQLITE_PRIVATE int sqlcipher_sqlite3VdbeParameterIndex(Vdbe*, const char*, int);
SQLITE_PRIVATE int sqlcipher_sqlite3TransferBindings(sqlcipher_sqlite3_stmt *, sqlcipher_sqlite3_stmt *);
-SQLITE_PRIVATE void sqlcipher_sqlite3ParserReset(Parse*);
+SQLITE_PRIVATE void sqlcipher_sqlite3ParseObjectInit(Parse*,sqlcipher_sqlite3*);
+SQLITE_PRIVATE void sqlcipher_sqlite3ParseObjectReset(Parse*);
+SQLITE_PRIVATE void *sqlcipher_sqlite3ParserAddCleanup(Parse*,void(*)(sqlcipher_sqlite3*,void*),void*);
#ifdef SQLITE_ENABLE_NORMALIZE
SQLITE_PRIVATE char *sqlcipher_sqlite3Normalize(Vdbe*, const char*);
#endif
@@ -20304,23 +20620,32 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Checkpoint(sqlcipher_sqlite3*, int, int, i
SQLITE_PRIVATE int sqlcipher_sqlite3WalDefaultHook(void*,sqlcipher_sqlite3*,const char*,int);
#endif
#ifndef SQLITE_OMIT_CTE
-SQLITE_PRIVATE With *sqlcipher_sqlite3WithAdd(Parse*,With*,Token*,ExprList*,Select*);
+SQLITE_PRIVATE Cte *sqlcipher_sqlite3CteNew(Parse*,Token*,ExprList*,Select*,u8);
+SQLITE_PRIVATE void sqlcipher_sqlite3CteDelete(sqlcipher_sqlite3*,Cte*);
+SQLITE_PRIVATE With *sqlcipher_sqlite3WithAdd(Parse*,With*,Cte*);
SQLITE_PRIVATE void sqlcipher_sqlite3WithDelete(sqlcipher_sqlite3*,With*);
-SQLITE_PRIVATE void sqlcipher_sqlite3WithPush(Parse*, With*, u8);
+SQLITE_PRIVATE With *sqlcipher_sqlite3WithPush(Parse*, With*, u8);
#else
-#define sqlcipher_sqlite3WithPush(x,y,z)
-#define sqlcipher_sqlite3WithDelete(x,y)
+# define sqlcipher_sqlite3CteNew(P,T,E,S) ((void*)0)
+# define sqlcipher_sqlite3CteDelete(D,C)
+# define sqlcipher_sqlite3CteWithAdd(P,W,C) ((void*)0)
+# define sqlcipher_sqlite3WithDelete(x,y)
+# define sqlcipher_sqlite3WithPush(x,y,z) ((void*)0)
#endif
#ifndef SQLITE_OMIT_UPSERT
-SQLITE_PRIVATE Upsert *sqlcipher_sqlite3UpsertNew(sqlcipher_sqlite3*,ExprList*,Expr*,ExprList*,Expr*);
+SQLITE_PRIVATE Upsert *sqlcipher_sqlite3UpsertNew(sqlcipher_sqlite3*,ExprList*,Expr*,ExprList*,Expr*,Upsert*);
SQLITE_PRIVATE void sqlcipher_sqlite3UpsertDelete(sqlcipher_sqlite3*,Upsert*);
SQLITE_PRIVATE Upsert *sqlcipher_sqlite3UpsertDup(sqlcipher_sqlite3*,Upsert*);
SQLITE_PRIVATE int sqlcipher_sqlite3UpsertAnalyzeTarget(Parse*,SrcList*,Upsert*);
SQLITE_PRIVATE void sqlcipher_sqlite3UpsertDoUpdate(Parse*,Upsert*,Table*,Index*,int);
+SQLITE_PRIVATE Upsert *sqlcipher_sqlite3UpsertOfIndex(Upsert*,Index*);
+SQLITE_PRIVATE int sqlcipher_sqlite3UpsertNextIsIPK(Upsert*);
#else
-#define sqlcipher_sqlite3UpsertNew(v,w,x,y,z) ((Upsert*)0)
+#define sqlcipher_sqlite3UpsertNew(u,v,w,x,y,z) ((Upsert*)0)
#define sqlcipher_sqlite3UpsertDelete(x,y)
-#define sqlcipher_sqlite3UpsertDup(x,y) ((Upsert*)0)
+#define sqlcipher_sqlite3UpsertDup(x,y) ((Upsert*)0)
+#define sqlcipher_sqlite3UpsertOfIndex(x,y) ((Upsert*)0)
+#define sqlcipher_sqlite3UpsertNextIsIPK(x) 0
#endif
@@ -20338,6 +20663,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3FkActions(Parse*, Table*, ExprList*, int,
SQLITE_PRIVATE int sqlcipher_sqlite3FkRequired(Parse*, Table*, int*, int);
SQLITE_PRIVATE u32 sqlcipher_sqlite3FkOldmask(Parse*, Table*);
SQLITE_PRIVATE FKey *sqlcipher_sqlite3FkReferences(Table *);
+SQLITE_PRIVATE void sqlcipher_sqlite3FkClearTriggerCache(sqlcipher_sqlite3*,int);
#else
#define sqlcipher_sqlite3FkActions(a,b,c,d,e,f)
#define sqlcipher_sqlite3FkCheck(a,b,c,d,e,f)
@@ -20345,6 +20671,7 @@ SQLITE_PRIVATE FKey *sqlcipher_sqlite3FkReferences(Table *);
#define sqlcipher_sqlite3FkOldmask(a,b) 0
#define sqlcipher_sqlite3FkRequired(a,b,c,d) 0
#define sqlcipher_sqlite3FkReferences(a) 0
+ #define sqlcipher_sqlite3FkClearTriggerCache(a,b)
#endif
#ifndef SQLITE_OMIT_FOREIGN_KEY
SQLITE_PRIVATE void sqlcipher_sqlite3FkDelete(sqlcipher_sqlite3 *, Table*);
@@ -20402,7 +20729,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3MemJournalOpen(sqlcipher_sqlite3_file *);
SQLITE_PRIVATE void sqlcipher_sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p);
#if SQLITE_MAX_EXPR_DEPTH>0
-SQLITE_PRIVATE int sqlcipher_sqlite3SelectExprHeight(Select *);
+SQLITE_PRIVATE int sqlcipher_sqlite3SelectExprHeight(const Select *);
SQLITE_PRIVATE int sqlcipher_sqlite3ExprCheckHeight(Parse*, int);
#else
#define sqlcipher_sqlite3SelectExprHeight(x) 0
@@ -20473,8 +20800,8 @@ SQLITE_API SQLITE_EXTERN void (SQLITE_CDECL *sqlcipher_sqlite3IoTrace)(const cha
*/
#ifdef SQLITE_MEMDEBUG
SQLITE_PRIVATE void sqlcipher_sqlite3MemdebugSetType(void*,u8);
-SQLITE_PRIVATE int sqlcipher_sqlite3MemdebugHasType(void*,u8);
-SQLITE_PRIVATE int sqlcipher_sqlite3MemdebugNoType(void*,u8);
+SQLITE_PRIVATE int sqlcipher_sqlite3MemdebugHasType(const void*,u8);
+SQLITE_PRIVATE int sqlcipher_sqlite3MemdebugNoType(const void*,u8);
#else
# define sqlcipher_sqlite3MemdebugSetType(X,Y) /* no-op */
# define sqlcipher_sqlite3MemdebugHasType(X,Y) 1
@@ -20499,10 +20826,10 @@ SQLITE_PRIVATE int sqlcipher_sqlite3DbpageRegister(sqlcipher_sqlite3*);
SQLITE_PRIVATE int sqlcipher_sqlite3DbstatRegister(sqlcipher_sqlite3*);
#endif
-SQLITE_PRIVATE int sqlcipher_sqlite3ExprVectorSize(Expr *pExpr);
-SQLITE_PRIVATE int sqlcipher_sqlite3ExprIsVector(Expr *pExpr);
+SQLITE_PRIVATE int sqlcipher_sqlite3ExprVectorSize(const Expr *pExpr);
+SQLITE_PRIVATE int sqlcipher_sqlite3ExprIsVector(const Expr *pExpr);
SQLITE_PRIVATE Expr *sqlcipher_sqlite3VectorFieldSubexpr(Expr*, int);
-SQLITE_PRIVATE Expr *sqlcipher_sqlite3ExprForVectorField(Parse*,Expr*,int);
+SQLITE_PRIVATE Expr *sqlcipher_sqlite3ExprForVectorField(Parse*,Expr*,int,int);
SQLITE_PRIVATE void sqlcipher_sqlite3VectorErrorMsg(Parse*, Expr*);
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
@@ -20512,191 +20839,52 @@ SQLITE_PRIVATE const char **sqlcipher_sqlite3CompileOptions(int *pnOpt);
#endif /* SQLITEINT_H */
/************** End of sqliteInt.h *******************************************/
-/************** Begin file crypto.c ******************************************/
+/************** Begin file os_common.h ***************************************/
/*
-** SQLCipher
-** http://sqlcipher.net
+** 2004 May 22
**
-** Copyright (c) 2008 - 2013, ZETETIC LLC
-** All rights reserved.
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
**
-** Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in the
-** documentation and/or other materials provided with the distribution.
-** * Neither the name of the ZETETIC LLC nor the
-** names of its contributors may be used to endorse or promote products
-** derived from this software without specific prior written permission.
+** 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 SOFTWARE IS PROVIDED BY ZETETIC LLC ''AS IS'' AND ANY
-** EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-** DISCLAIMED. IN NO EVENT SHALL ZETETIC LLC BE LIABLE FOR ANY
-** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+******************************************************************************
+**
+** 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.
*/
-/* BEGIN SQLCIPHER */
-#ifdef SQLITE_HAS_CODEC
+#ifndef _OS_COMMON_H_
+#define _OS_COMMON_H_
-/* #include <assert.h> */
-/************** Include sqlcipher.h in the middle of crypto.c ****************/
-/************** Begin file sqlcipher.h ***************************************/
/*
-** SQLCipher
-** sqlcipher.h developed by Stephen Lombardo (Zetetic LLC)
-** sjlombardo at zetetic dot net
-** http://zetetic.net
-**
-** Copyright (c) 2008, ZETETIC LLC
-** All rights reserved.
-**
-** Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in the
-** documentation and/or other materials provided with the distribution.
-** * Neither the name of the ZETETIC LLC nor the
-** names of its contributors may be used to endorse or promote products
-** derived from this software without specific prior written permission.
-**
-** THIS SOFTWARE IS PROVIDED BY ZETETIC LLC ''AS IS'' AND ANY
-** EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-** DISCLAIMED. IN NO EVENT SHALL ZETETIC LLC BE LIABLE FOR ANY
-** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-**
+** 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.
*/
-/* BEGIN SQLCIPHER */
-#ifdef SQLITE_HAS_CODEC
-#ifndef SQLCIPHER_H
-#define SQLCIPHER_H
-
-#define SQLCIPHER_HMAC_SHA1 0
-#define SQLCIPHER_HMAC_SHA1_LABEL "HMAC_SHA1"
-#define SQLCIPHER_HMAC_SHA256 1
-#define SQLCIPHER_HMAC_SHA256_LABEL "HMAC_SHA256"
-#define SQLCIPHER_HMAC_SHA512 2
-#define SQLCIPHER_HMAC_SHA512_LABEL "HMAC_SHA512"
-
-
-#define SQLCIPHER_PBKDF2_HMAC_SHA1 0
-#define SQLCIPHER_PBKDF2_HMAC_SHA1_LABEL "PBKDF2_HMAC_SHA1"
-#define SQLCIPHER_PBKDF2_HMAC_SHA256 1
-#define SQLCIPHER_PBKDF2_HMAC_SHA256_LABEL "PBKDF2_HMAC_SHA256"
-#define SQLCIPHER_PBKDF2_HMAC_SHA512 2
-#define SQLCIPHER_PBKDF2_HMAC_SHA512_LABEL "PBKDF2_HMAC_SHA512"
-
-
-typedef struct {
- int (*activate)(void *ctx);
- int (*deactivate)(void *ctx);
- const char* (*get_provider_name)(void *ctx);
- int (*add_random)(void *ctx, void *buffer, int length);
- int (*random)(void *ctx, void *buffer, int length);
- int (*hmac)(void *ctx, int algorithm, unsigned char *hmac_key, int key_sz, unsigned char *in, int in_sz, unsigned char *in2, int in2_sz, unsigned char *out);
- int (*kdf)(void *ctx, int algorithm, const unsigned char *pass, int pass_sz, unsigned char* salt, int salt_sz, int workfactor, int key_sz, unsigned char *key);
- int (*cipher)(void *ctx, int mode, unsigned char *key, int key_sz, unsigned char *iv, unsigned char *in, int in_sz, unsigned char *out);
- const char* (*get_cipher)(void *ctx);
- int (*get_key_sz)(void *ctx);
- int (*get_iv_sz)(void *ctx);
- int (*get_block_sz)(void *ctx);
- int (*get_hmac_sz)(void *ctx, int algorithm);
- int (*ctx_init)(void **ctx);
- int (*ctx_free)(void **ctx);
- int (*fips_status)(void *ctx);
- const char* (*get_provider_version)(void *ctx);
-} sqlcipher_provider;
-
-/* utility functions */
-void* sqlcipher_malloc(u64);
-void sqlcipher_mlock(void *, u64);
-void sqlcipher_munlock(void *, u64);
-void* sqlcipher_memset(void *, unsigned char, u64);
-int sqlcipher_ismemset(const void *, unsigned char, u64);
-int sqlcipher_memcmp(const void *, const void *, int);
-void sqlcipher_free(void *, u64);
-char* sqlcipher_version();
-
-/* provider interfaces */
-int sqlcipher_register_provider(sqlcipher_provider *);
-sqlcipher_provider* sqlcipher_get_provider(void);
-
-#define SQLCIPHER_MUTEX_PROVIDER 0
-#define SQLCIPHER_MUTEX_PROVIDER_ACTIVATE 1
-#define SQLCIPHER_MUTEX_PROVIDER_RAND 2
-#define SQLCIPHER_MUTEX_RESERVED1 3
-#define SQLCIPHER_MUTEX_RESERVED2 4
-#define SQLCIPHER_MUTEX_RESERVED3 5
-#define SQLCIPHER_MUTEX_COUNT 6
-
-sqlcipher_sqlite3_mutex* sqlcipher_mutex(int);
-
-#endif
+#ifdef MEMORY_DEBUG
+# error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
#endif
-/* END SQLCIPHER */
-
-/************** End of sqlcipher.h *******************************************/
-/************** Continuing where we left off in crypto.c *********************/
-/************** Include crypto.h in the middle of crypto.c *******************/
-/************** Begin file crypto.h ******************************************/
/*
-** SQLCipher
-** crypto.h developed by Stephen Lombardo (Zetetic LLC)
-** sjlombardo at zetetic dot net
-** http://zetetic.net
-**
-** Copyright (c) 2008, ZETETIC LLC
-** All rights reserved.
-**
-** Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in the
-** documentation and/or other materials provided with the distribution.
-** * Neither the name of the ZETETIC LLC nor the
-** names of its contributors may be used to endorse or promote products
-** derived from this software without specific prior written permission.
-**
-** THIS SOFTWARE IS PROVIDED BY ZETETIC LLC ''AS IS'' AND ANY
-** EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-** DISCLAIMED. IN NO EVENT SHALL ZETETIC LLC BE LIABLE FOR ANY
-** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-**
+** Macros for performance tracing. Normally turned off. Only works
+** on i486 hardware.
*/
-/* BEGIN SQLCIPHER */
-#ifdef SQLITE_HAS_CODEC
-#ifndef CRYPTO_H
-#define CRYPTO_H
+#ifdef SQLITE_PERFORMANCE_TRACE
-/* #include "sqliteInt.h" */
-/************** Include btreeInt.h in the middle of crypto.h *****************/
-/************** Begin file btreeInt.h ****************************************/
/*
-** 2004 April 6
+** 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:
@@ -20705,4906 +20893,944 @@ sqlcipher_sqlite3_mutex* sqlcipher_mutex(int);
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
-*************************************************************************
-** This file implements an external (disk-based) database using BTrees.
-** For a detailed discussion of BTrees, refer to
-**
-** Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3:
-** "Sorting And Searching", pages 473-480. Addison-Wesley
-** Publishing Company, Reading, Massachusetts.
-**
-** The basic idea is that each page of the file contains N database
-** entries and N+1 pointers to subpages.
-**
-** ----------------------------------------------------------------
-** | Ptr(0) | Key(0) | Ptr(1) | Key(1) | ... | Key(N-1) | Ptr(N) |
-** ----------------------------------------------------------------
-**
-** All of the keys on the page that Ptr(0) points to have values less
-** than Key(0). All of the keys on page Ptr(1) and its subpages have
-** values greater than Key(0) and less than Key(1). All of the keys
-** on Ptr(N) and its subpages have values greater than Key(N-1). And
-** so forth.
-**
-** Finding a particular key requires reading O(log(M)) pages from the
-** disk where M is the number of entries in the tree.
-**
-** In this implementation, a single file can hold one or more separate
-** BTrees. Each BTree is identified by the index of its root page. The
-** key and data for any entry are combined to form the "payload". A
-** fixed amount of payload can be carried directly on the database
-** page. If the payload is larger than the preset amount then surplus
-** bytes are stored on overflow pages. The payload for an entry
-** and the preceding pointer are combined to form a "Cell". Each
-** page has a small header which contains the Ptr(N) pointer and other
-** information such as the size of key and data.
-**
-** FORMAT DETAILS
-**
-** The file is divided into pages. The first page is called page 1,
-** the second is page 2, and so forth. A page number of zero indicates
-** "no such page". The page size can be any power of 2 between 512 and 65536.
-** Each page can be either a btree page, a freelist page, an overflow
-** page, or a pointer-map page.
-**
-** The first page is always a btree page. The first 100 bytes of the first
-** page contain a special header (the "file header") that describes the file.
-** The format of the file header is as follows:
-**
-** OFFSET SIZE DESCRIPTION
-** 0 16 Header string: "SQLite format 3\000"
-** 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 (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
-** 36 4 Number of freelist pages in the file
-** 40 60 15 4-byte meta values passed to higher layers
-**
-** 40 4 Schema cookie
-** 44 4 File format of schema layer
-** 48 4 Size of page cache
-** 52 4 Largest root-page (auto/incr_vacuum)
-** 56 4 1=UTF-8 2=UTF16le 3=UTF16be
-** 60 4 User version
-** 64 4 Incremental vacuum mode
-** 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).
-**
-** The file change counter is incremented when the database is changed
-** This counter allows other processes to know when the file has changed
-** and thus when they need to flush their cache.
-**
-** The max embedded payload fraction is the amount of the total usable
-** space in a page that can be consumed by a single cell for standard
-** B-tree (non-LEAFDATA) tables. A value of 255 means 100%. The default
-** is to limit the maximum cell size so that at least 4 cells will fit
-** on one page. Thus the default max embedded payload fraction is 64.
-**
-** If the payload for a cell is larger than the max payload, then extra
-** payload is spilled to overflow pages. Once an overflow page is allocated,
-** as many bytes as possible are moved into the overflow pages without letting
-** the cell size drop below the min embedded payload fraction.
-**
-** The min leaf payload fraction is like the min embedded payload fraction
-** except that it applies to leaf nodes in a LEAFDATA tree. The maximum
-** payload fraction for a LEAFDATA tree is always 100% (or 255) and it
-** not specified in the header.
-**
-** Each btree pages is divided into three sections: The header, the
-** cell pointer array, and the cell content area. Page 1 also has a 100-byte
-** file header that occurs before the page header.
-**
-** |----------------|
-** | file header | 100 bytes. Page 1 only.
-** |----------------|
-** | page header | 8 bytes for leaves. 12 bytes for interior nodes
-** |----------------|
-** | cell pointer | | 2 bytes per cell. Sorted order.
-** | array | | Grows downward
-** | | v
-** |----------------|
-** | unallocated |
-** | space |
-** |----------------| ^ Grows upwards
-** | cell content | | Arbitrary order interspersed with freeblocks.
-** | area | | and free space fragments.
-** |----------------|
-**
-** The page headers looks like this:
-**
-** OFFSET SIZE DESCRIPTION
-** 0 1 Flags. 1: intkey, 2: zerodata, 4: leafdata, 8: leaf
-** 1 2 byte offset to the first freeblock
-** 3 2 number of cells on this page
-** 5 2 first byte of the cell content area
-** 7 1 number of fragmented free bytes
-** 8 4 Right child (the Ptr(N) value). Omitted on leaves.
-**
-** The flags define the format of this btree page. The leaf flag means that
-** this page has no children. The zerodata flag means that this page carries
-** only keys and no data. The intkey flag means that the key is an integer
-** which is stored in the key size entry of the cell header rather than in
-** the payload area.
-**
-** The cell pointer array begins on the first byte after the page header.
-** The cell pointer array contains zero or more 2-byte numbers which are
-** offsets from the beginning of the page to the cell content in the cell
-** content area. The cell pointers occur in sorted order. The system strives
-** to keep free space after the last cell pointer so that new cells can
-** be easily added without having to defragment the page.
-**
-** Cell content is stored at the very end of the page and grows toward the
-** beginning of the page.
-**
-** Unused space within the cell content area is collected into a linked list of
-** freeblocks. Each freeblock is at least 4 bytes in size. The byte offset
-** to the first freeblock is given in the header. Freeblocks occur in
-** increasing order. Because a freeblock must be at least 4 bytes in size,
-** any group of 3 or fewer unused bytes in the cell content area cannot
-** exist on the freeblock chain. A group of 3 or fewer free bytes is called
-** a fragment. The total number of bytes in all fragments is recorded.
-** in the page header at offset 7.
-**
-** SIZE DESCRIPTION
-** 2 Byte offset of the next freeblock
-** 2 Bytes in this freeblock
-**
-** Cells are of variable length. Cells are stored in the cell content area at
-** the end of the page. Pointers to the cells are in the cell pointer array
-** that immediately follows the page header. Cells is not necessarily
-** contiguous or in order, but cell pointers are contiguous and in order.
-**
-** Cell content makes use of variable length integers. A variable
-** length integer is 1 to 9 bytes where the lower 7 bits of each
-** byte are used. The integer consists of all bytes that have bit 8 set and
-** the first byte with bit 8 clear. The most significant byte of the integer
-** appears first. A variable-length integer may not be more than 9 bytes long.
-** As a special case, all 8 bytes of the 9th byte are used as data. This
-** allows a 64-bit integer to be encoded in 9 bytes.
-**
-** 0x00 becomes 0x00000000
-** 0x7f becomes 0x0000007f
-** 0x81 0x00 becomes 0x00000080
-** 0x82 0x00 becomes 0x00000100
-** 0x80 0x7f becomes 0x0000007f
-** 0x8a 0x91 0xd1 0xac 0x78 becomes 0x12345678
-** 0x81 0x81 0x81 0x81 0x01 becomes 0x10204081
-**
-** Variable length integers are used for rowids and to hold the number of
-** bytes of key and data in a btree cell.
-**
-** The content of a cell looks like this:
-**
-** SIZE DESCRIPTION
-** 4 Page number of the left child. Omitted if leaf flag is set.
-** var Number of bytes of data. Omitted if the zerodata flag is set.
-** var Number of bytes of key. Or the key itself if intkey flag is set.
-** * Payload
-** 4 First page of the overflow chain. Omitted if no overflow
-**
-** Overflow pages form a linked list. Each page except the last is completely
-** filled with data (pagesize - 4 bytes). The last page can have as little
-** as 1 byte of data.
-**
-** SIZE DESCRIPTION
-** 4 Page number of next overflow page
-** * Data
-**
-** Freelist pages come in two subtypes: trunk pages and leaf pages. The
-** file header points to the first in a linked list of trunk page. Each trunk
-** page points to multiple leaf pages. The content of a leaf page is
-** unspecified. A trunk page looks like this:
+******************************************************************************
**
-** SIZE DESCRIPTION
-** 4 Page number of next trunk page
-** 4 Number of leaf pointers on this page
-** * zero or more pages numbers of leaves
+** This file contains inline asm code for retrieving "high-performance"
+** counters for x86 and x86_64 class CPUs.
*/
-/* #include "sqliteInt.h" */
-
+#ifndef SQLITE_HWTIME_H
+#define SQLITE_HWTIME_H
-/* The following value is the maximum cell size assuming a maximum page
-** size give above.
+/*
+** 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.
*/
-#define MX_CELL_SIZE(pBt) ((int)(pBt->pageSize-8))
+#if !defined(__STRICT_ANSI__) && \
+ (defined(__GNUC__) || defined(_MSC_VER)) && \
+ (defined(i386) || defined(__i386__) || defined(_M_IX86))
-/* The maximum number of cells on a single page of the database. This
-** assumes a minimum cell size of 6 bytes (4 bytes for the cell itself
-** plus 2 bytes for the index to the cell in the page header). Such
-** small cells will be rare, but they are possible.
-*/
-#define MX_CELL(pBt) ((pBt->pageSize-8)/6)
+ #if defined(__GNUC__)
-/* Forward declarations */
-typedef struct MemPage MemPage;
-typedef struct BtLock BtLock;
-typedef struct CellInfo CellInfo;
+ __inline__ sqlite_uint64 sqlcipher_sqlite3Hwtime(void){
+ unsigned int lo, hi;
+ __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
+ return (sqlite_uint64)hi << 32 | lo;
+ }
-/*
-** This is a magic string that appears at the beginning of every
-** SQLite database in order to identify the file as a real database.
-**
-** You can change this value at compile-time by specifying a
-** -DSQLITE_FILE_HEADER="..." on the compiler command-line. The
-** header must be exactly 16 bytes including the zero-terminator so
-** the string itself should be 15 characters long. If you change
-** the header, then your custom library will not be able to read
-** databases generated by the standard tools and the standard tools
-** will not be able to read databases created by your custom library.
-*/
-#ifndef SQLITE_FILE_HEADER /* 123456789 123456 */
-# define SQLITE_FILE_HEADER "SQLite format 3"
-#endif
+ #elif defined(_MSC_VER)
-/*
-** Page type flags. An ORed combination of these flags appear as the
-** first byte of on-disk image of every BTree page.
-*/
-#define PTF_INTKEY 0x01
-#define PTF_ZERODATA 0x02
-#define PTF_LEAFDATA 0x04
-#define PTF_LEAF 0x08
+ __declspec(naked) __inline sqlite_uint64 __cdecl sqlcipher_sqlite3Hwtime(void){
+ __asm {
+ rdtsc
+ ret ; return value at EDX:EAX
+ }
+ }
-/*
-** An instance of this object stores information about each a single database
-** page that has been loaded into memory. The information in this object
-** is derived from the raw on-disk page content.
-**
-** As each database page is loaded into memory, the pager allocats an
-** instance of this object and zeros the first 8 bytes. (This is the
-** "extra" information associated with each page of the pager.)
-**
-** Access to all fields of this structure is controlled by the mutex
-** stored in MemPage.pBt->mutex.
-*/
-struct MemPage {
- u8 isInit; /* True if previously initialized. MUST BE FIRST! */
- u8 bBusy; /* Prevent endless loops on corrupt database files */
- u8 intKey; /* True if table b-trees. False for index b-trees */
- u8 intKeyLeaf; /* True if the leaf of an intKey table */
- Pgno pgno; /* Page number for this page */
- /* Only the first 8 bytes (above) are zeroed by pager.c when a new page
- ** is allocated. All fields that follow must be initialized before use */
- u8 leaf; /* True if a leaf page */
- u8 hdrOffset; /* 100 for page 1. 0 otherwise */
- u8 childPtrSize; /* 0 if leaf==1. 4 if leaf==0 */
- u8 max1bytePayload; /* min(maxLocal,127) */
- u8 nOverflow; /* Number of overflow cell bodies in aCell[] */
- u16 maxLocal; /* Copy of BtShared.maxLocal or BtShared.maxLeaf */
- u16 minLocal; /* Copy of BtShared.minLocal or BtShared.minLeaf */
- u16 cellOffset; /* Index in aData of first cell pointer */
- int nFree; /* Number of free bytes on the page. -1 for unknown */
- u16 nCell; /* Number of cells on this page, local and ovfl */
- u16 maskPage; /* Mask for page offset */
- u16 aiOvfl[4]; /* Insert the i-th overflow cell before the aiOvfl-th
- ** non-overflow cell */
- u8 *apOvfl[4]; /* Pointers to the body of overflow cells */
- BtShared *pBt; /* Pointer to BtShared that this page is part of */
- u8 *aData; /* Pointer to disk image of the page data */
- u8 *aDataEnd; /* One byte past the end of usable data */
- u8 *aCellIdx; /* The cell index area */
- u8 *aDataOfst; /* Same as aData for leaves. aData+4 for interior */
- DbPage *pDbPage; /* Pager page handle */
- u16 (*xCellSize)(MemPage*,u8*); /* cellSizePtr method */
- void (*xParseCell)(MemPage*,u8*,CellInfo*); /* btreeParseCell method */
-};
+ #endif
-/*
-** A linked list of the following structures is stored at BtShared.pLock.
-** Locks are added (or upgraded from READ_LOCK to WRITE_LOCK) when a cursor
-** is opened on the table with root page BtShared.iTable. Locks are removed
-** from this list when a transaction is committed or rolled back, or when
-** a btree handle is closed.
-*/
-struct BtLock {
- Btree *pBtree; /* Btree handle holding this lock */
- Pgno iTable; /* Root page of table */
- u8 eLock; /* READ_LOCK or WRITE_LOCK */
- BtLock *pNext; /* Next in BtShared.pLock list */
-};
+#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__))
-/* Candidate values for BtLock.eLock */
-#define READ_LOCK 1
-#define WRITE_LOCK 2
+ __inline__ sqlite_uint64 sqlcipher_sqlite3Hwtime(void){
+ unsigned long val;
+ __asm__ __volatile__ ("rdtsc" : "=A" (val));
+ return val;
+ }
-/* A Btree handle
-**
-** A database connection contains a pointer to an instance of
-** this object for every database file that it has open. This structure
-** is opaque to the database connection. The database connection cannot
-** see the internals of this structure and only deals with pointers to
-** this structure.
-**
-** For some database files, the same underlying database cache might be
-** shared between multiple connections. In that case, each connection
-** has it own instance of this object. But each instance of this object
-** points to the same BtShared object. The database cache and the
-** schema associated with the database file are all contained within
-** the BtShared object.
-**
-** All fields in this structure are accessed under sqlcipher_sqlite3.mutex.
-** The pBt pointer itself may not be changed while there exists cursors
-** in the referenced BtShared that point back to this Btree since those
-** cursors have to go through this Btree to find their BtShared and
-** they often do so without holding sqlcipher_sqlite3.mutex.
-*/
-struct Btree {
- sqlcipher_sqlite3 *db; /* The database connection holding this btree */
- BtShared *pBt; /* Sharable content of this btree */
- u8 inTrans; /* TRANS_NONE, TRANS_READ or TRANS_WRITE */
- u8 sharable; /* True if we can share pBt with another db */
- u8 locked; /* True if db currently has pBt locked */
- u8 hasIncrblobCur; /* True if there are one or more Incrblob cursors */
- int wantToLock; /* Number of nested calls to sqlcipher_sqlite3BtreeEnter() */
- int nBackup; /* Number of backup operations reading this btree */
- u32 iDataVersion; /* Combines with pBt->pPager->iDataVersion */
- Btree *pNext; /* List of other sharable Btrees from the same db */
- Btree *pPrev; /* Back pointer of the same list */
-#ifdef SQLITE_DEBUG
- u64 nSeek; /* Calls to sqlcipher_sqlite3BtreeMovetoUnpacked() */
-#endif
-#ifndef SQLITE_OMIT_SHARED_CACHE
- BtLock lock; /* Object used to lock page 1 */
-#endif
-};
+#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__))
-/*
-** Btree.inTrans may take one of the following values.
-**
-** If the shared-data extension is enabled, there may be multiple users
-** of the Btree structure. At most one of these may open a write transaction,
-** but any number may have active read transactions.
-**
-** These values must match SQLITE_TXN_NONE, SQLITE_TXN_READ, and
-** SQLITE_TXN_WRITE
-*/
-#define TRANS_NONE 0
-#define TRANS_READ 1
-#define TRANS_WRITE 2
+ __inline__ sqlite_uint64 sqlcipher_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;
+ }
-#if TRANS_NONE!=SQLITE_TXN_NONE
-# error wrong numeric code for no-transaction
-#endif
-#if TRANS_READ!=SQLITE_TXN_READ
-# error wrong numeric code for read-transaction
-#endif
-#if TRANS_WRITE!=SQLITE_TXN_WRITE
-# error wrong numeric code for write-transaction
-#endif
+#else
+ /*
+ ** asm() is needed for hardware timing support. Without asm(),
+ ** disable the sqlcipher_sqlite3Hwtime() routine.
+ **
+ ** sqlcipher_sqlite3Hwtime() is only used for some obscure debugging
+ ** and analysis configurations, not in any deliverable, so this
+ ** should not be a great loss.
+ */
+SQLITE_PRIVATE sqlite_uint64 sqlcipher_sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
-/*
-** An instance of this object represents a single database file.
-**
-** A single database file can be in use at the same time by two
-** or more database connections. When two or more connections are
-** sharing the same database file, each connection has it own
-** private Btree object for the file and each of those Btrees points
-** to this one BtShared object. BtShared.nRef is the number of
-** connections currently sharing this database file.
-**
-** Fields in this structure are accessed under the BtShared.mutex
-** mutex, except for nRef and pNext which are accessed under the
-** global SQLITE_MUTEX_STATIC_MAIN mutex. The pPager field
-** may not be modified once it is initially set as long as nRef>0.
-** The pSchema field may be set once under BtShared.mutex and
-** thereafter is unchanged as long as nRef>0.
-**
-** isPending:
-**
-** If a BtShared client fails to obtain a write-lock on a database
-** table (because there exists one or more read-locks on the table),
-** the shared-cache enters 'pending-lock' state and isPending is
-** set to true.
-**
-** The shared-cache leaves the 'pending lock' state when either of
-** the following occur:
-**
-** 1) The current writer (BtShared.pWriter) concludes its transaction, OR
-** 2) The number of locks held by other connections drops to zero.
-**
-** while in the 'pending-lock' state, no connection may start a new
-** transaction.
-**
-** This feature is included to help prevent writer-starvation.
-*/
-struct BtShared {
- Pager *pPager; /* The page cache */
- sqlcipher_sqlite3 *db; /* Database connection currently using this Btree */
- BtCursor *pCursor; /* A list of all open cursors */
- MemPage *pPage1; /* First page of the database */
- u8 openFlags; /* Flags to sqlcipher_sqlite3BtreeOpen() */
-#ifndef SQLITE_OMIT_AUTOVACUUM
- u8 autoVacuum; /* True if auto-vacuum is enabled */
- u8 incrVacuum; /* True if incr-vacuum is enabled */
- u8 bDoTruncate; /* True to truncate db on commit */
#endif
- u8 inTransaction; /* Transaction state */
- u8 max1bytePayload; /* Maximum first byte of cell for a 1-byte payload */
- u8 nReserveWanted; /* Desired number of extra bytes per page */
- u16 btsFlags; /* Boolean parameters. See BTS_* macros below */
- u16 maxLocal; /* Maximum local payload in non-LEAFDATA tables */
- u16 minLocal; /* Minimum local payload in non-LEAFDATA tables */
- u16 maxLeaf; /* Maximum local payload in a LEAFDATA table */
- u16 minLeaf; /* Minimum local payload in a LEAFDATA table */
- u32 pageSize; /* Total number of bytes on a page */
- u32 usableSize; /* Number of usable bytes on each page */
- int nTransaction; /* Number of open transactions (read + write) */
- u32 nPage; /* Number of pages in the database */
- void *pSchema; /* Pointer to space allocated by sqlcipher_sqlite3BtreeSchema() */
- void (*xFreeSchema)(void*); /* Destructor for BtShared.pSchema */
- sqlcipher_sqlite3_mutex *mutex; /* Non-recursive mutex required to access this object */
- Bitvec *pHasContent; /* Set of pages moved to free-list this transaction */
-#ifndef SQLITE_OMIT_SHARED_CACHE
- int nRef; /* Number of references to this structure */
- BtShared *pNext; /* Next on a list of sharable BtShared structs */
- BtLock *pLock; /* List of locks held on this shared-btree struct */
- Btree *pWriter; /* Btree with currently open write transaction */
-#endif
- u8 *pTmpSpace; /* Temp space sufficient to hold a single cell */
-};
-/*
-** Allowed values for BtShared.btsFlags
-*/
-#define BTS_READ_ONLY 0x0001 /* Underlying file is readonly */
-#define BTS_PAGESIZE_FIXED 0x0002 /* Page size can no longer be changed */
-#define BTS_SECURE_DELETE 0x0004 /* PRAGMA secure_delete is enabled */
-#define BTS_OVERWRITE 0x0008 /* Overwrite deleted content with zeros */
-#define BTS_FAST_SECURE 0x000c /* Combination of the previous two */
-#define BTS_INITIALLY_EMPTY 0x0010 /* Database was empty at trans start */
-#define BTS_NO_WAL 0x0020 /* Do not open write-ahead-log files */
-#define BTS_EXCLUSIVE 0x0040 /* pWriter has an exclusive lock */
-#define BTS_PENDING 0x0080 /* Waiting for read-locks to clear */
-
-/*
-** An instance of the following structure is used to hold information
-** about a cell. The parseCellPtr() function fills in this structure
-** based on information extract from the raw disk page.
-*/
-struct CellInfo {
- i64 nKey; /* The key for INTKEY tables, or nPayload otherwise */
- u8 *pPayload; /* Pointer to the start of payload */
- u32 nPayload; /* Bytes of payload */
- u16 nLocal; /* Amount of payload held locally, not on overflow */
- u16 nSize; /* Size of the cell content on the main b-tree page */
-};
+#endif /* !defined(SQLITE_HWTIME_H) */
-/*
-** Maximum depth of an SQLite B-Tree structure. Any B-Tree deeper than
-** this will be declared corrupt. This value is calculated based on a
-** maximum database size of 2^31 pages a minimum fanout of 2 for a
-** root-node and 3 for all other internal nodes.
-**
-** If a tree that appears to be taller than this is encountered, it is
-** assumed that the database is corrupt.
-*/
-#define BTCURSOR_MAX_DEPTH 20
+/************** End of hwtime.h **********************************************/
+/************** Continuing where we left off in os_common.h ******************/
-/*
-** A cursor is a pointer to a particular entry within a particular
-** b-tree within a database file.
-**
-** The entry is identified by its MemPage and the index in
-** MemPage.aCell[] of the entry.
-**
-** A single database file can be shared by two more database connections,
-** but cursors cannot be shared. Each cursor is associated with a
-** particular database connection identified BtCursor.pBtree.db.
-**
-** Fields in this structure are accessed under the BtShared.mutex
-** found at self->pBt->mutex.
-**
-** skipNext meaning:
-** The meaning of skipNext depends on the value of eState:
-**
-** eState Meaning of skipNext
-** VALID skipNext is meaningless and is ignored
-** INVALID skipNext is meaningless and is ignored
-** SKIPNEXT sqlcipher_sqlite3BtreeNext() is a no-op if skipNext>0 and
-** sqlcipher_sqlite3BtreePrevious() is no-op if skipNext<0.
-** REQUIRESEEK restoreCursorPosition() restores the cursor to
-** eState=SKIPNEXT if skipNext!=0
-** FAULT skipNext holds the cursor fault error code.
-*/
-struct BtCursor {
- u8 eState; /* One of the CURSOR_XXX constants (see below) */
- u8 curFlags; /* zero or more BTCF_* flags defined below */
- u8 curPagerFlags; /* Flags to send to sqlcipher_sqlite3PagerGet() */
- u8 hints; /* As configured by CursorSetHints() */
- int skipNext; /* Prev() is noop if negative. Next() is noop if positive.
- ** Error code if eState==CURSOR_FAULT */
- Btree *pBtree; /* The Btree to which this cursor belongs */
- Pgno *aOverflow; /* Cache of overflow page locations */
- void *pKey; /* Saved key that was cursor last known position */
- /* All fields above are zeroed when the cursor is allocated. See
- ** sqlcipher_sqlite3BtreeCursorZero(). Fields that follow must be manually
- ** initialized. */
-#define BTCURSOR_FIRST_UNINIT pBt /* Name of first uninitialized field */
- BtShared *pBt; /* The BtShared this cursor points to */
- BtCursor *pNext; /* Forms a linked list of all cursors */
- CellInfo info; /* A parse of the cell we are pointing at */
- i64 nKey; /* Size of pKey, or last integer key */
- Pgno pgnoRoot; /* The root page of this tree */
- i8 iPage; /* Index of current page in apPage */
- u8 curIntKey; /* Value of apPage[0]->intKey */
- u16 ix; /* Current index for apPage[iPage] */
- u16 aiIdx[BTCURSOR_MAX_DEPTH-1]; /* Current index in apPage[i] */
- struct KeyInfo *pKeyInfo; /* Arg passed to comparison function */
- MemPage *pPage; /* Current page */
- MemPage *apPage[BTCURSOR_MAX_DEPTH-1]; /* Stack of parents of current page */
-};
+static sqlite_uint64 g_start;
+static sqlite_uint64 g_elapsed;
+#define TIMER_START g_start=sqlcipher_sqlite3Hwtime()
+#define TIMER_END g_elapsed=sqlcipher_sqlite3Hwtime()-g_start
+#define TIMER_ELAPSED g_elapsed
+#else
+#define TIMER_START
+#define TIMER_END
+#define TIMER_ELAPSED ((sqlite_uint64)0)
+#endif
/*
-** Legal values for BtCursor.curFlags
+** 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.
*/
-#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 */
-#define BTCF_Multiple 0x20 /* Maybe another cursor on the same btree */
-#define BTCF_Pinned 0x40 /* Cursor is busy and cannot be moved */
+#if defined(SQLITE_TEST)
+SQLITE_API extern int sqlcipher_sqlite3_io_error_hit;
+SQLITE_API extern int sqlcipher_sqlite3_io_error_hardhit;
+SQLITE_API extern int sqlcipher_sqlite3_io_error_pending;
+SQLITE_API extern int sqlcipher_sqlite3_io_error_persist;
+SQLITE_API extern int sqlcipher_sqlite3_io_error_benign;
+SQLITE_API extern int sqlcipher_sqlite3_diskfull_pending;
+SQLITE_API extern int sqlcipher_sqlite3_diskfull;
+#define SimulateIOErrorBenign(X) sqlcipher_sqlite3_io_error_benign=(X)
+#define SimulateIOError(CODE) \
+ if( (sqlcipher_sqlite3_io_error_persist && sqlcipher_sqlite3_io_error_hit) \
+ || sqlcipher_sqlite3_io_error_pending-- == 1 ) \
+ { local_ioerr(); CODE; }
+static void local_ioerr(){
+ IOTRACE(("IOERR\n"));
+ sqlcipher_sqlite3_io_error_hit++;
+ if( !sqlcipher_sqlite3_io_error_benign ) sqlcipher_sqlite3_io_error_hardhit++;
+}
+#define SimulateDiskfullError(CODE) \
+ if( sqlcipher_sqlite3_diskfull_pending ){ \
+ if( sqlcipher_sqlite3_diskfull_pending == 1 ){ \
+ local_ioerr(); \
+ sqlcipher_sqlite3_diskfull = 1; \
+ sqlcipher_sqlite3_io_error_hit = 1; \
+ CODE; \
+ }else{ \
+ sqlcipher_sqlite3_diskfull_pending--; \
+ } \
+ }
+#else
+#define SimulateIOErrorBenign(X)
+#define SimulateIOError(A)
+#define SimulateDiskfullError(A)
+#endif /* defined(SQLITE_TEST) */
/*
-** Potential values for BtCursor.eState.
-**
-** 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 sqlcipher_sqlite3BtreeNext() or sqlcipher_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
-** in variables BtCursor.pKey and BtCursor.nKey. When a cursor is in
-** this state, restoreCursorPosition() can be called to attempt to
-** seek the cursor to the saved position.
-**
-** CURSOR_FAULT:
-** An unrecoverable error (an I/O error or a malloc failure) has occurred
-** on a different connection that shares the BtShared cache with this
-** cursor. The error has left the cache in an inconsistent state.
-** Do nothing else with this cursor. Any attempt to use the cursor
-** should return the error code stored in BtCursor.skipNext
+** When testing, keep a count of the number of open files.
*/
-#define CURSOR_VALID 0
-#define CURSOR_INVALID 1
-#define CURSOR_SKIPNEXT 2
-#define CURSOR_REQUIRESEEK 3
-#define CURSOR_FAULT 4
+#if defined(SQLITE_TEST)
+SQLITE_API extern int sqlcipher_sqlite3_open_file_count;
+#define OpenCounter(X) sqlcipher_sqlite3_open_file_count+=(X)
+#else
+#define OpenCounter(X)
+#endif /* defined(SQLITE_TEST) */
-/*
-** The database page the PENDING_BYTE occupies. This page is never used.
-*/
-# define PENDING_BYTE_PAGE(pBt) PAGER_MJ_PGNO(pBt)
+#endif /* !defined(_OS_COMMON_H_) */
-/*
-** These macros define the location of the pointer-map entry for a
-** database page. The first argument to each is the number of usable
-** bytes on each page of the database (often 1024). The second is the
-** page number to look up in the pointer map.
-**
-** PTRMAP_PAGENO returns the database page number of the pointer-map
-** page that stores the required pointer. PTRMAP_PTROFFSET returns
-** the offset of the requested map entry.
+/************** End of os_common.h *******************************************/
+/************** Begin file ctime.c *******************************************/
+/* DO NOT EDIT!
+** This file is automatically generated by the script in the canonical
+** SQLite source tree at tool/mkctimec.tcl.
**
-** If the pgno argument passed to PTRMAP_PAGENO is a pointer-map page,
-** then pgno is returned. So (pgno==PTRMAP_PAGENO(pgsz, pgno)) can be
-** used to test if pgno is a pointer-map page. PTRMAP_ISPAGE implements
-** this test.
+** To modify this header, edit any of the various lists in that script
+** which specify categories of generated conditionals in this file.
*/
-#define PTRMAP_PAGENO(pBt, pgno) ptrmapPageno(pBt, pgno)
-#define PTRMAP_PTROFFSET(pgptrmap, pgno) (5*(pgno-pgptrmap-1))
-#define PTRMAP_ISPAGE(pBt, pgno) (PTRMAP_PAGENO((pBt),(pgno))==(pgno))
/*
-** The pointer map is a lookup table that identifies the parent page for
-** each child page in the database file. The parent page is the page that
-** contains a pointer to the child. Every page in the database contains
-** 0 or 1 parent pages. (In this context 'database page' refers
-** to any page that is not part of the pointer map itself.) Each pointer map
-** entry consists of a single byte 'type' and a 4 byte parent page number.
-** The PTRMAP_XXX identifiers below are the valid types.
-**
-** The purpose of the pointer map is to facility moving pages from one
-** position in the file to another as part of autovacuum. When a page
-** is moved, the pointer in its parent must be updated to point to the
-** new location. The pointer map is used to locate the parent page quickly.
-**
-** PTRMAP_ROOTPAGE: The database page is a root-page. The page-number is not
-** used in this case.
+** 2010 February 23
**
-** PTRMAP_FREEPAGE: The database page is an unused (free) page. The page-number
-** is not used in this case.
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
**
-** PTRMAP_OVERFLOW1: The database page is the first page in a list of
-** overflow pages. The page number identifies the page that
-** contains the cell with a pointer to this overflow page.
+** 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.
**
-** PTRMAP_OVERFLOW2: The database page is the second or later page in a list of
-** overflow pages. The page-number identifies the previous
-** page in the overflow page list.
+*************************************************************************
**
-** PTRMAP_BTREE: The database page is a non-root btree page. The page number
-** identifies the parent page in the btree.
-*/
-#define PTRMAP_ROOTPAGE 1
-#define PTRMAP_FREEPAGE 2
-#define PTRMAP_OVERFLOW1 3
-#define PTRMAP_OVERFLOW2 4
-#define PTRMAP_BTREE 5
-
-/* A bunch of assert() statements to check the transaction state variables
-** of handle p (type Btree*) are internally consistent.
+** This file implements routines used to report what compile-time options
+** SQLite was built with.
*/
-#define btreeIntegrity(p) \
- assert( p->pBt->inTransaction!=TRANS_NONE || p->pBt->nTransaction==0 ); \
- assert( p->pBt->inTransaction>=p->inTrans );
-
+#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS /* IMP: R-16824-07538 */
/*
-** The ISAUTOVACUUM macro is used within balance_nonroot() to determine
-** if the database supports auto-vacuum or not. Because it is used
-** within an expression that is an argument to another macro
-** (sqliteMallocRaw), it is not possible to use conditional compilation.
-** So, this macro is defined instead.
+** Include the configuration header output by 'configure' if we're using the
+** autoconf-based build
*/
-#ifndef SQLITE_OMIT_AUTOVACUUM
-#define ISAUTOVACUUM (pBt->autoVacuum)
-#else
-#define ISAUTOVACUUM 0
+#if defined(_HAVE_SQLITE_CONFIG_H) && !defined(SQLITECONFIG_H)
+/* #include "config.h" */
+#define SQLITECONFIG_H 1
#endif
+/* These macros are provided to "stringify" the value of the define
+** for those options in which the value is meaningful. */
+#define CTIMEOPT_VAL_(opt) #opt
+#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
-/*
-** This structure is passed around through all the sanity checking routines
-** in order to keep track of some global state information.
-**
-** The aRef[] array is allocated so that there is 1 bit for each page in
-** the database. As the integrity-check proceeds, for each page used in
-** the database the corresponding bit is set. This allows integrity-check to
-** detect pages that are used twice and orphaned pages (both of which
-** indicate corruption).
-*/
-typedef struct IntegrityCk IntegrityCk;
-struct IntegrityCk {
- BtShared *pBt; /* The tree being checked out */
- Pager *pPager; /* The associated pager. Also accessible by pBt->pPager */
- u8 *aPgRef; /* 1 bit per page in the db (see above) */
- Pgno nPage; /* Number of pages in the database */
- int mxErr; /* Stop accumulating errors when this reaches zero */
- int nErr; /* Number of messages written to zErrMsg so far */
- int bOomFault; /* A memory allocation error has occurred */
- const char *zPfx; /* Error message prefix */
- Pgno v1; /* Value for first %u substitution in zPfx */
- int v2; /* Value for second %d substitution in zPfx */
- StrAccum errMsg; /* Accumulate the error message text here */
- u32 *heap; /* Min-heap used for analyzing cell coverage */
- sqlcipher_sqlite3 *db; /* Database connection running the check */
-};
+/* Like CTIMEOPT_VAL, but especially for SQLITE_DEFAULT_LOOKASIDE. This
+** option requires a separate macro because legal values contain a single
+** comma. e.g. (-DSQLITE_DEFAULT_LOOKASIDE="100,100") */
+#define CTIMEOPT_VAL2_(opt1,opt2) #opt1 "," #opt2
+#define CTIMEOPT_VAL2(opt) CTIMEOPT_VAL2_(opt)
+/* #include "sqliteInt.h" */
/*
-** Routines to read or write a two- and four-byte big-endian integer values.
+** An array of names of all compile-time options. This array should
+** be sorted A-Z.
+**
+** This array looks large, but in a typical installation actually uses
+** only a handful of compile-time options, so most times this array is usually
+** rather short and uses little memory space.
*/
-#define get2byte(x) ((x)[0]<<8 | (x)[1])
-#define put2byte(p,v) ((p)[0] = (u8)((v)>>8), (p)[1] = (u8)(v))
-#define get4byte sqlcipher_sqlite3Get4byte
-#define put4byte sqlcipher_sqlite3Put4byte
+static const char * const sqlcipher_sqlite3azCompileOpt[] = {
-/*
-** get2byteAligned(), unlike get2byte(), requires that its argument point to a
-** two-byte aligned address. get2bytea() is only used for accessing the
-** cell addresses in a btree header.
-*/
-#if SQLITE_BYTEORDER==4321
-# define get2byteAligned(x) (*(u16*)(x))
-#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4008000
-# define get2byteAligned(x) __builtin_bswap16(*(u16*)(x))
-#elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
-# define get2byteAligned(x) _byteswap_ushort(*(u16*)(x))
-#else
-# define get2byteAligned(x) ((x)[0]<<8 | (x)[1])
+#ifdef SQLITE_32BIT_ROWID
+ "32BIT_ROWID",
#endif
-
-/************** End of btreeInt.h ********************************************/
-/************** Continuing where we left off in crypto.h *********************/
-/* #include "pager.h" */
-
-/* extensions defined in pager.c */
-SQLITE_PRIVATE void *sqlcipher_sqlite3PagerGetCodec(Pager*);
-SQLITE_PRIVATE void sqlcipher_sqlite3PagerSetCodec(Pager*, void *(*)(void*,void*,Pgno,int), void (*)(void*,int,int), void (*)(void*), void *);
-SQLITE_API int sqlcipher_sqlite3pager_is_mj_pgno(Pager*, Pgno);
-SQLITE_API void sqlcipher_sqlite3pager_error(Pager*, int);
-SQLITE_API void sqlcipher_sqlite3pager_reset(Pager *pPager);
-
-#if !defined (SQLCIPHER_CRYPTO_CC) \
- && !defined (SQLCIPHER_CRYPTO_LIBTOMCRYPT) \
- && !defined (SQLCIPHER_CRYPTO_NSS) \
- && !defined (SQLCIPHER_CRYPTO_OPENSSL)
-#define SQLCIPHER_CRYPTO_OPENSSL
+#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC
+ "4_BYTE_ALIGNED_MALLOC",
#endif
-
-#define FILE_HEADER_SZ 16
-
-#define CIPHER_XSTR(s) CIPHER_STR(s)
-#define CIPHER_STR(s) #s
-
-#ifndef CIPHER_VERSION_NUMBER
-#define CIPHER_VERSION_NUMBER 4.4.3
+#ifdef SQLITE_64BIT_STATS
+ "64BIT_STATS",
#endif
-
-#ifndef CIPHER_VERSION_BUILD
-#define CIPHER_VERSION_BUILD community
+#ifdef SQLITE_ALLOW_COVERING_INDEX_SCAN
+# if SQLITE_ALLOW_COVERING_INDEX_SCAN != 1
+ "ALLOW_COVERING_INDEX_SCAN=" CTIMEOPT_VAL(SQLITE_ALLOW_COVERING_INDEX_SCAN),
+# endif
#endif
-
-#define CIPHER_DECRYPT 0
-#define CIPHER_ENCRYPT 1
-
-#define CIPHER_READ_CTX 0
-#define CIPHER_WRITE_CTX 1
-#define CIPHER_READWRITE_CTX 2
-
-#ifndef PBKDF2_ITER
-#define PBKDF2_ITER 256000
+#ifdef SQLITE_ALLOW_URI_AUTHORITY
+ "ALLOW_URI_AUTHORITY",
#endif
-
-/* possible flags for cipher_ctx->flags */
-#define CIPHER_FLAG_HMAC 0x01
-#define CIPHER_FLAG_LE_PGNO 0x02
-#define CIPHER_FLAG_BE_PGNO 0x04
-
-#ifndef DEFAULT_CIPHER_FLAGS
-#define DEFAULT_CIPHER_FLAGS CIPHER_FLAG_HMAC | CIPHER_FLAG_LE_PGNO
+#ifdef SQLITE_ATOMIC_INTRINSICS
+ "ATOMIC_INTRINSICS=" CTIMEOPT_VAL(SQLITE_ATOMIC_INTRINSICS),
#endif
-
-
-/* by default, sqlcipher will use a reduced number of iterations to generate
- the HMAC key / or transform a raw cipher key
- */
-#ifndef FAST_PBKDF2_ITER
-#define FAST_PBKDF2_ITER 2
+#ifdef SQLITE_BITMASK_TYPE
+ "BITMASK_TYPE=" CTIMEOPT_VAL(SQLITE_BITMASK_TYPE),
#endif
-
-/* this if a fixed random array that will be xor'd with the database salt to ensure that the
- salt passed to the HMAC key derivation function is not the same as that used to derive
- the encryption key. This can be overridden at compile time but it will make the resulting
- binary incompatible with the default builds when using HMAC. A future version of SQLcipher
- will likely allow this to be defined at runtime via pragma */
-#ifndef HMAC_SALT_MASK
-#define HMAC_SALT_MASK 0x3a
+#ifdef SQLITE_BUG_COMPATIBLE_20160819
+ "BUG_COMPATIBLE_20160819",
#endif
-
-#ifndef CIPHER_MAX_IV_SZ
-#define CIPHER_MAX_IV_SZ 16
+#ifdef SQLITE_CASE_SENSITIVE_LIKE
+ "CASE_SENSITIVE_LIKE",
#endif
-
-#ifndef CIPHER_MAX_KEY_SZ
-#define CIPHER_MAX_KEY_SZ 64
+#ifdef SQLITE_CHECK_PAGES
+ "CHECK_PAGES",
#endif
-
-#ifdef __ANDROID__
-#include <android/log.h>
+#if defined(__clang__) && defined(__clang_major__)
+ "COMPILER=clang-" CTIMEOPT_VAL(__clang_major__) "."
+ CTIMEOPT_VAL(__clang_minor__) "."
+ CTIMEOPT_VAL(__clang_patchlevel__),
+#elif defined(_MSC_VER)
+ "COMPILER=msvc-" CTIMEOPT_VAL(_MSC_VER),
+#elif defined(__GNUC__) && defined(__VERSION__)
+ "COMPILER=gcc-" __VERSION__,
#endif
-
-#ifdef CODEC_DEBUG
-#ifdef __ANDROID__
-#define CODEC_TRACE(...) {__android_log_print(ANDROID_LOG_DEBUG, "sqlcipher", __VA_ARGS__);}
-#else
-#define CODEC_TRACE(...) {fprintf(stderr, __VA_ARGS__);fflush(stderr);}
+#ifdef SQLITE_COVERAGE_TEST
+ "COVERAGE_TEST",
#endif
-#else
-#define CODEC_TRACE(...)
+#ifdef SQLITE_DEBUG
+ "DEBUG",
#endif
-
-#ifdef CODEC_DEBUG_MUTEX
-#define CODEC_TRACE_MUTEX(...) CODEC_TRACE(__VA_ARGS__)
-#else
-#define CODEC_TRACE_MUTEX(...)
+#ifdef SQLITE_DEFAULT_AUTOMATIC_INDEX
+ "DEFAULT_AUTOMATIC_INDEX",
#endif
-
-#ifdef CODEC_DEBUG_MEMORY
-#define CODEC_TRACE_MEMORY(...) CODEC_TRACE(__VA_ARGS__)
-#else
-#define CODEC_TRACE_MEMORY(...)
+#ifdef SQLITE_DEFAULT_AUTOVACUUM
+ "DEFAULT_AUTOVACUUM",
#endif
-
-#ifdef CODEC_DEBUG_PAGEDATA
-#define CODEC_HEXDUMP(DESC,BUFFER,LEN) \
- { \
- int __pctr; \
- printf(DESC); \
- for(__pctr=0; __pctr < LEN; __pctr++) { \
- if(__pctr % 16 == 0) printf("\n%05x: ",__pctr); \
- printf("%02x ",((unsigned char*) BUFFER)[__pctr]); \
- } \
- printf("\n"); \
- fflush(stdout); \
- }
-#else
-#define CODEC_HEXDUMP(DESC,BUFFER,LEN)
+#ifdef SQLITE_DEFAULT_CACHE_SIZE
+ "DEFAULT_CACHE_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_CACHE_SIZE),
#endif
-
-/* end extensions defined in pager.c */
-
-/*
-** Simple shared routines for converting hex char strings to binary data
- */
-static int cipher_hex2int(char c) {
- return (c>='0' && c<='9') ? (c)-'0' :
- (c>='A' && c<='F') ? (c)-'A'+10 :
- (c>='a' && c<='f') ? (c)-'a'+10 : 0;
-}
-
-static void cipher_hex2bin(const unsigned char *hex, int sz, unsigned char *out){
- int i;
- for(i = 0; i < sz; i += 2){
- out[i/2] = (cipher_hex2int(hex[i])<<4) | cipher_hex2int(hex[i+1]);
- }
-}
-
-static void cipher_bin2hex(const unsigned char* in, int sz, char *out) {
- int i;
- for(i=0; i < sz; i++) {
- sqlcipher_sqlite3_snprintf(3, out + (i*2), "%02x ", in[i]);
- }
-}
-
-static int cipher_isHex(const unsigned char *hex, int sz){
- int i;
- for(i = 0; i < sz; i++) {
- unsigned char c = hex[i];
- if ((c < '0' || c > '9') &&
- (c < 'A' || c > 'F') &&
- (c < 'a' || c > 'f')) {
- return 0;
- }
- }
- return 1;
-}
-
-/* extensions defined in crypto_impl.c */
-/* the default implementation of SQLCipher uses a cipher_ctx
- to keep track of read / write state separately. The following
- struct and associated functions are defined here */
-typedef struct {
- int derive_key;
- int pass_sz;
- unsigned char *key;
- unsigned char *hmac_key;
- unsigned char *pass;
- char *keyspec;
-} cipher_ctx;
-
-
-typedef struct {
- int store_pass;
- int kdf_iter;
- int fast_kdf_iter;
- int kdf_salt_sz;
- int key_sz;
- int iv_sz;
- int block_sz;
- int page_sz;
- int keyspec_sz;
- int reserve_sz;
- int hmac_sz;
- int plaintext_header_sz;
- int hmac_algorithm;
- int kdf_algorithm;
- unsigned int skip_read_hmac;
- unsigned int need_kdf_salt;
- unsigned int flags;
- unsigned char *kdf_salt;
- unsigned char *hmac_kdf_salt;
- unsigned char *buffer;
- Btree *pBt;
- cipher_ctx *read_ctx;
- cipher_ctx *write_ctx;
- sqlcipher_provider *provider;
- void *provider_ctx;
-} codec_ctx ;
-
-/* crypto.c functions */
-int sqlcipher_codec_pragma(sqlcipher_sqlite3*, int, Parse*, const char *, const char*);
-SQLITE_PRIVATE int sqlcipher_sqlite3CodecAttach(sqlcipher_sqlite3*, int, const void *, int);
-SQLITE_PRIVATE void sqlcipher_sqlite3CodecGetKey(sqlcipher_sqlite3*, int, void**, int*);
-void sqlcipher_exportFunc(sqlcipher_sqlite3_context *, int, sqlcipher_sqlite3_value **);
-
-/* crypto_impl.c functions */
-
-void sqlcipher_init_memmethods(void);
-
-/* activation and initialization */
-void sqlcipher_activate(void);
-void sqlcipher_deactivate(void);
-
-int sqlcipher_codec_ctx_init(codec_ctx **, Db *, Pager *, const void *, int);
-void sqlcipher_codec_ctx_free(codec_ctx **);
-int sqlcipher_codec_key_derive(codec_ctx *);
-int sqlcipher_codec_key_copy(codec_ctx *, int);
-
-/* page cipher implementation */
-int sqlcipher_page_cipher(codec_ctx *, int, Pgno, int, int, unsigned char *, unsigned char *);
-
-/* context setters & getters */
-void sqlcipher_codec_ctx_set_error(codec_ctx *, int);
-
-void sqlcipher_codec_get_pass(codec_ctx *, void **, int *);
-int sqlcipher_codec_ctx_set_pass(codec_ctx *, const void *, int, int);
-void sqlcipher_codec_get_keyspec(codec_ctx *, void **zKey, int *nKey);
-
-int sqlcipher_codec_ctx_set_pagesize(codec_ctx *, int);
-int sqlcipher_codec_ctx_get_pagesize(codec_ctx *);
-int sqlcipher_codec_ctx_get_reservesize(codec_ctx *);
-
-void sqlcipher_set_default_pagesize(int page_size);
-int sqlcipher_get_default_pagesize(void);
-
-void sqlcipher_set_default_kdf_iter(int iter);
-int sqlcipher_get_default_kdf_iter(void);
-int sqlcipher_codec_ctx_set_kdf_iter(codec_ctx *, int);
-int sqlcipher_codec_ctx_get_kdf_iter(codec_ctx *ctx);
-
-int sqlcipher_codec_ctx_set_kdf_salt(codec_ctx *ctx, unsigned char *salt, int sz);
-int sqlcipher_codec_ctx_get_kdf_salt(codec_ctx *ctx, void **salt);
-
-int sqlcipher_codec_ctx_set_fast_kdf_iter(codec_ctx *, int);
-int sqlcipher_codec_ctx_get_fast_kdf_iter(codec_ctx *);
-
-const char* sqlcipher_codec_ctx_get_cipher(codec_ctx *ctx);
-
-void* sqlcipher_codec_ctx_get_data(codec_ctx *);
-
-void sqlcipher_set_default_use_hmac(int use);
-int sqlcipher_get_default_use_hmac(void);
-
-void sqlcipher_set_hmac_salt_mask(unsigned char mask);
-unsigned char sqlcipher_get_hmac_salt_mask(void);
-
-int sqlcipher_codec_ctx_set_use_hmac(codec_ctx *ctx, int use);
-int sqlcipher_codec_ctx_get_use_hmac(codec_ctx *ctx);
-
-int sqlcipher_codec_ctx_set_flag(codec_ctx *ctx, unsigned int flag);
-int sqlcipher_codec_ctx_unset_flag(codec_ctx *ctx, unsigned int flag);
-int sqlcipher_codec_ctx_get_flag(codec_ctx *ctx, unsigned int flag);
-
-const char* sqlcipher_codec_get_cipher_provider(codec_ctx *ctx);
-int sqlcipher_codec_ctx_migrate(codec_ctx *ctx);
-int sqlcipher_codec_add_random(codec_ctx *ctx, const char *data, int random_sz);
-int sqlcipher_cipher_profile(sqlcipher_sqlite3 *db, const char *destination);
-int sqlcipher_codec_get_store_pass(codec_ctx *ctx);
-void sqlcipher_codec_get_pass(codec_ctx *ctx, void **zKey, int *nKey);
-void sqlcipher_codec_set_store_pass(codec_ctx *ctx, int value);
-int sqlcipher_codec_fips_status(codec_ctx *ctx);
-const char* sqlcipher_codec_get_provider_version(codec_ctx *ctx);
-
-int sqlcipher_set_default_plaintext_header_size(int size);
-int sqlcipher_get_default_plaintext_header_size(void);
-int sqlcipher_codec_ctx_set_plaintext_header_size(codec_ctx *ctx, int size);
-int sqlcipher_codec_ctx_get_plaintext_header_size(codec_ctx *ctx);
-
-int sqlcipher_set_default_hmac_algorithm(int algorithm);
-int sqlcipher_get_default_hmac_algorithm(void);
-int sqlcipher_codec_ctx_set_hmac_algorithm(codec_ctx *ctx, int algorithm);
-int sqlcipher_codec_ctx_get_hmac_algorithm(codec_ctx *ctx);
-
-int sqlcipher_set_default_kdf_algorithm(int algorithm);
-int sqlcipher_get_default_kdf_algorithm(void);
-int sqlcipher_codec_ctx_set_kdf_algorithm(codec_ctx *ctx, int algorithm);
-int sqlcipher_codec_ctx_get_kdf_algorithm(codec_ctx *ctx);
-
-void sqlcipher_set_mem_security(int);
-int sqlcipher_get_mem_security(void);
-
-int sqlcipher_find_db_index(sqlcipher_sqlite3 *db, const char *zDb);
-
-int sqlcipher_codec_ctx_integrity_check(codec_ctx *, Parse *, char *);
-
+#ifdef SQLITE_DEFAULT_CKPTFULLFSYNC
+ "DEFAULT_CKPTFULLFSYNC",
#endif
+#ifdef SQLITE_DEFAULT_FILE_FORMAT
+ "DEFAULT_FILE_FORMAT=" CTIMEOPT_VAL(SQLITE_DEFAULT_FILE_FORMAT),
#endif
-/* END SQLCIPHER */
-
-/************** End of crypto.h **********************************************/
-/************** Continuing where we left off in crypto.c *********************/
-
-#ifdef SQLCIPHER_EXT
-#include "sqlcipher_ext.h"
+#ifdef SQLITE_DEFAULT_FILE_PERMISSIONS
+ "DEFAULT_FILE_PERMISSIONS=" CTIMEOPT_VAL(SQLITE_DEFAULT_FILE_PERMISSIONS),
#endif
-
-#ifdef SQLCIPHER_TEST
-static int cipher_fail_next_encrypt = 0;
-static int cipher_fail_next_decrypt = 0;
+#ifdef SQLITE_DEFAULT_FOREIGN_KEYS
+ "DEFAULT_FOREIGN_KEYS",
#endif
-
-/* Generate code to return a string value */
-static void codec_vdbe_return_string(Parse *pParse, const char *zLabel, const char *value, int value_type){
- Vdbe *v = sqlcipher_sqlite3GetVdbe(pParse);
- sqlcipher_sqlite3VdbeSetNumCols(v, 1);
- sqlcipher_sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLabel, SQLITE_STATIC);
- sqlcipher_sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, value, value_type);
- sqlcipher_sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
-}
-
-static int codec_set_btree_to_codec_pagesize(sqlcipher_sqlite3 *db, Db *pDb, codec_ctx *ctx) {
- int rc, page_sz, reserve_sz;
-
- page_sz = sqlcipher_codec_ctx_get_pagesize(ctx);
- reserve_sz = sqlcipher_codec_ctx_get_reservesize(ctx);
-
- CODEC_TRACE("codec_set_btree_to_codec_pagesize: sqlcipher_sqlite3BtreeSetPageSize() size=%d reserve=%d\n", page_sz, reserve_sz);
-
- CODEC_TRACE_MUTEX("codec_set_btree_to_codec_pagesize: entering database mutex %p\n", db->mutex);
- sqlcipher_sqlite3_mutex_enter(db->mutex);
- CODEC_TRACE_MUTEX("codec_set_btree_to_codec_pagesize: entered database mutex %p\n", db->mutex);
- db->nextPagesize = page_sz;
-
- /* before forcing the page size we need to unset the BTS_PAGESIZE_FIXED flag, else
- sqliteBtreeSetPageSize will block the change */
- pDb->pBt->pBt->btsFlags &= ~BTS_PAGESIZE_FIXED;
- rc = sqlcipher_sqlite3BtreeSetPageSize(pDb->pBt, page_sz, reserve_sz, 0);
-
- CODEC_TRACE("codec_set_btree_to_codec_pagesize: sqlcipher_sqlite3BtreeSetPageSize returned %d\n", rc);
-
- CODEC_TRACE_MUTEX("codec_set_btree_to_codec_pagesize: leaving database mutex %p\n", db->mutex);
- sqlcipher_sqlite3_mutex_leave(db->mutex);
- CODEC_TRACE_MUTEX("codec_set_btree_to_codec_pagesize: left database mutex %p\n", db->mutex);
-
- return rc;
-}
-
-static int codec_set_pass_key(sqlcipher_sqlite3* db, int nDb, const void *zKey, int nKey, int for_ctx) {
- struct Db *pDb = &db->aDb[nDb];
- CODEC_TRACE("codec_set_pass_key: entered db=%p nDb=%d zKey=%s nKey=%d for_ctx=%d\n", db, nDb, (char *)zKey, nKey, for_ctx);
- if(pDb->pBt) {
- codec_ctx *ctx = (codec_ctx*) sqlcipher_sqlite3PagerGetCodec(pDb->pBt->pBt->pPager);
-
- if(ctx) return sqlcipher_codec_ctx_set_pass(ctx, zKey, nKey, for_ctx);
- }
- return SQLITE_ERROR;
-}
-
-int sqlcipher_codec_pragma(sqlcipher_sqlite3* db, int iDb, Parse *pParse, const char *zLeft, const char *zRight) {
- struct Db *pDb = &db->aDb[iDb];
- codec_ctx *ctx = NULL;
- int rc;
-
- if(pDb->pBt) {
- ctx = (codec_ctx*) sqlcipher_sqlite3PagerGetCodec(pDb->pBt->pBt->pPager);
- }
-
- CODEC_TRACE("sqlcipher_codec_pragma: entered db=%p iDb=%d pParse=%p zLeft=%s zRight=%s ctx=%p\n", db, iDb, pParse, zLeft, zRight, ctx);
-
-#ifdef SQLCIPHER_EXT
- if( sqlcipher_sqlite3StrICmp(zLeft, "cipher_license")==0 && zRight ){
- char *license_result = sqlcipher_sqlite3_mprintf("%d", sqlcipher_license_key(zRight));
- codec_vdbe_return_string(pParse, "cipher_license", license_result, P4_DYNAMIC);
- } else
- if( sqlcipher_sqlite3StrICmp(zLeft, "cipher_license")==0 && !zRight ){
- if(ctx) {
- char *license_result = sqlcipher_sqlite3_mprintf("%d", ctx
- ? sqlcipher_license_key_status(ctx->provider)
- : SQLITE_ERROR);
- codec_vdbe_return_string(pParse, "cipher_license", license_result, P4_DYNAMIC);
- }
- } else
+#ifdef SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT
+ "DEFAULT_JOURNAL_SIZE_LIMIT=" CTIMEOPT_VAL(SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT),
#endif
-#ifdef SQLCIPHER_TEST
- if( sqlcipher_sqlite3StrICmp(zLeft,"cipher_fail_next_encrypt")==0 ){
- if( zRight ) {
- cipher_fail_next_encrypt = sqlcipher_sqlite3GetBoolean(zRight,1);
- } else {
- char *fail = sqlcipher_sqlite3_mprintf("%d", cipher_fail_next_encrypt);
- codec_vdbe_return_string(pParse, "cipher_fail_next_encrypt", fail, P4_DYNAMIC);
- }
- }else
- if( sqlcipher_sqlite3StrICmp(zLeft,"cipher_fail_next_decrypt")==0 ){
- if( zRight ) {
- cipher_fail_next_decrypt = sqlcipher_sqlite3GetBoolean(zRight,1);
- } else {
- char *fail = sqlcipher_sqlite3_mprintf("%d", cipher_fail_next_decrypt);
- codec_vdbe_return_string(pParse, "cipher_fail_next_decrypt", fail, P4_DYNAMIC);
- }
- }else
+#ifdef SQLITE_DEFAULT_LOCKING_MODE
+ "DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE),
#endif
- if( sqlcipher_sqlite3StrICmp(zLeft, "cipher_fips_status")== 0 && !zRight ){
- if(ctx) {
- char *fips_mode_status = sqlcipher_sqlite3_mprintf("%d", sqlcipher_codec_fips_status(ctx));
- codec_vdbe_return_string(pParse, "cipher_fips_status", fips_mode_status, P4_DYNAMIC);
- }
- } else
- if( sqlcipher_sqlite3StrICmp(zLeft, "cipher_store_pass")==0 && zRight ) {
- if(ctx) {
- char *deprecation = "PRAGMA cipher_store_pass is deprecated, please remove from use";
- sqlcipher_codec_set_store_pass(ctx, sqlcipher_sqlite3GetBoolean(zRight, 1));
- codec_vdbe_return_string(pParse, "cipher_store_pass", deprecation, P4_TRANSIENT);
- sqlcipher_sqlite3_log(SQLITE_WARNING, deprecation);
- }
- } else
- if( sqlcipher_sqlite3StrICmp(zLeft, "cipher_store_pass")==0 && !zRight ) {
- if(ctx){
- char *store_pass_value = sqlcipher_sqlite3_mprintf("%d", sqlcipher_codec_get_store_pass(ctx));
- codec_vdbe_return_string(pParse, "cipher_store_pass", store_pass_value, P4_DYNAMIC);
- }
- }
- if( sqlcipher_sqlite3StrICmp(zLeft, "cipher_profile")== 0 && zRight ){
- char *profile_status = sqlcipher_sqlite3_mprintf("%d", sqlcipher_cipher_profile(db, zRight));
- codec_vdbe_return_string(pParse, "cipher_profile", profile_status, P4_DYNAMIC);
- } else
- if( sqlcipher_sqlite3StrICmp(zLeft, "cipher_add_random")==0 && zRight ){
- if(ctx) {
- char *add_random_status = sqlcipher_sqlite3_mprintf("%d", sqlcipher_codec_add_random(ctx, zRight, sqlcipher_sqlite3Strlen30(zRight)));
- codec_vdbe_return_string(pParse, "cipher_add_random", add_random_status, P4_DYNAMIC);
- }
- } else
- if( sqlcipher_sqlite3StrICmp(zLeft, "cipher_migrate")==0 && !zRight ){
- if(ctx){
- char *migrate_status = sqlcipher_sqlite3_mprintf("%d", sqlcipher_codec_ctx_migrate(ctx));
- codec_vdbe_return_string(pParse, "cipher_migrate", migrate_status, P4_DYNAMIC);
- }
- } else
- if( sqlcipher_sqlite3StrICmp(zLeft, "cipher_provider")==0 && !zRight ){
- if(ctx) { codec_vdbe_return_string(pParse, "cipher_provider",
- sqlcipher_codec_get_cipher_provider(ctx), P4_TRANSIENT);
- }
- } else
- if( sqlcipher_sqlite3StrICmp(zLeft, "cipher_provider_version")==0 && !zRight){
- if(ctx) { codec_vdbe_return_string(pParse, "cipher_provider_version",
- sqlcipher_codec_get_provider_version(ctx), P4_TRANSIENT);
- }
- } else
- if( sqlcipher_sqlite3StrICmp(zLeft, "cipher_version")==0 && !zRight ){
- codec_vdbe_return_string(pParse, "cipher_version", sqlcipher_version(), P4_DYNAMIC);
- }else
- if( sqlcipher_sqlite3StrICmp(zLeft, "cipher")==0 ){
- if(ctx) {
- if( zRight ) {
- const char* message = "PRAGMA cipher is no longer supported.";
- codec_vdbe_return_string(pParse, "cipher", message, P4_TRANSIENT);
- sqlcipher_sqlite3_log(SQLITE_WARNING, message);
- }else {
- codec_vdbe_return_string(pParse, "cipher", sqlcipher_codec_ctx_get_cipher(ctx), P4_TRANSIENT);
- }
- }
- }else
- if( sqlcipher_sqlite3StrICmp(zLeft, "rekey_cipher")==0 && zRight ){
- const char* message = "PRAGMA rekey_cipher is no longer supported.";
- codec_vdbe_return_string(pParse, "rekey_cipher", message, P4_TRANSIENT);
- sqlcipher_sqlite3_log(SQLITE_WARNING, message);
- }else
- if( sqlcipher_sqlite3StrICmp(zLeft,"cipher_default_kdf_iter")==0 ){
- if( zRight ) {
- sqlcipher_set_default_kdf_iter(atoi(zRight)); /* change default KDF iterations */
- } else {
- char *kdf_iter = sqlcipher_sqlite3_mprintf("%d", sqlcipher_get_default_kdf_iter());
- codec_vdbe_return_string(pParse, "cipher_default_kdf_iter", kdf_iter, P4_DYNAMIC);
- }
- }else
- if( sqlcipher_sqlite3StrICmp(zLeft, "kdf_iter")==0 ){
- if(ctx) {
- if( zRight ) {
- sqlcipher_codec_ctx_set_kdf_iter(ctx, atoi(zRight)); /* change of RW PBKDF2 iteration */
- } else {
- char *kdf_iter = sqlcipher_sqlite3_mprintf("%d", sqlcipher_codec_ctx_get_kdf_iter(ctx));
- codec_vdbe_return_string(pParse, "kdf_iter", kdf_iter, P4_DYNAMIC);
- }
- }
- }else
- if( sqlcipher_sqlite3StrICmp(zLeft, "fast_kdf_iter")==0){
- if(ctx) {
- if( zRight ) {
- char *deprecation = "PRAGMA fast_kdf_iter is deprecated, please remove from use";
- sqlcipher_codec_ctx_set_fast_kdf_iter(ctx, atoi(zRight)); /* change of RW PBKDF2 iteration */
- codec_vdbe_return_string(pParse, "fast_kdf_iter", deprecation, P4_TRANSIENT);
- sqlcipher_sqlite3_log(SQLITE_WARNING, deprecation);
- } else {
- char *fast_kdf_iter = sqlcipher_sqlite3_mprintf("%d", sqlcipher_codec_ctx_get_fast_kdf_iter(ctx));
- codec_vdbe_return_string(pParse, "fast_kdf_iter", fast_kdf_iter, P4_DYNAMIC);
- }
- }
- }else
- if( sqlcipher_sqlite3StrICmp(zLeft, "rekey_kdf_iter")==0 && zRight ){
- const char* message = "PRAGMA rekey_kdf_iter is no longer supported.";
- codec_vdbe_return_string(pParse, "rekey_kdf_iter", message, P4_TRANSIENT);
- sqlcipher_sqlite3_log(SQLITE_WARNING, message);
- }else
- if( sqlcipher_sqlite3StrICmp(zLeft,"cipher_page_size")==0 ){
- if(ctx) {
- if( zRight ) {
- int size = atoi(zRight);
- rc = sqlcipher_codec_ctx_set_pagesize(ctx, size);
- if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc);
- rc = codec_set_btree_to_codec_pagesize(db, pDb, ctx);
- if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc);
- } else {
- char * page_size = sqlcipher_sqlite3_mprintf("%d", sqlcipher_codec_ctx_get_pagesize(ctx));
- codec_vdbe_return_string(pParse, "cipher_page_size", page_size, P4_DYNAMIC);
- }
- }
- }else
- if( sqlcipher_sqlite3StrICmp(zLeft,"cipher_default_page_size")==0 ){
- if( zRight ) {
- sqlcipher_set_default_pagesize(atoi(zRight));
- } else {
- char *default_page_size = sqlcipher_sqlite3_mprintf("%d", sqlcipher_get_default_pagesize());
- codec_vdbe_return_string(pParse, "cipher_default_page_size", default_page_size, P4_DYNAMIC);
- }
- }else
- if( sqlcipher_sqlite3StrICmp(zLeft,"cipher_default_use_hmac")==0 ){
- if( zRight ) {
- sqlcipher_set_default_use_hmac(sqlcipher_sqlite3GetBoolean(zRight,1));
- } else {
- char *default_use_hmac = sqlcipher_sqlite3_mprintf("%d", sqlcipher_get_default_use_hmac());
- codec_vdbe_return_string(pParse, "cipher_default_use_hmac", default_use_hmac, P4_DYNAMIC);
- }
- }else
- if( sqlcipher_sqlite3StrICmp(zLeft,"cipher_use_hmac")==0 ){
- if(ctx) {
- if( zRight ) {
- rc = sqlcipher_codec_ctx_set_use_hmac(ctx, sqlcipher_sqlite3GetBoolean(zRight,1));
- if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc);
- /* since the use of hmac has changed, the page size may also change */
- rc = codec_set_btree_to_codec_pagesize(db, pDb, ctx);
- if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc);
- } else {
- char *hmac_flag = sqlcipher_sqlite3_mprintf("%d", sqlcipher_codec_ctx_get_use_hmac(ctx));
- codec_vdbe_return_string(pParse, "cipher_use_hmac", hmac_flag, P4_DYNAMIC);
- }
- }
- }else
- if( sqlcipher_sqlite3StrICmp(zLeft,"cipher_hmac_pgno")==0 ){
- if(ctx) {
- if(zRight) {
- char *deprecation = "PRAGMA cipher_hmac_pgno is deprecated, please remove from use";
- /* clear both pgno endian flags */
- if(sqlcipher_sqlite3StrICmp(zRight, "le") == 0) {
- sqlcipher_codec_ctx_unset_flag(ctx, CIPHER_FLAG_BE_PGNO);
- sqlcipher_codec_ctx_set_flag(ctx, CIPHER_FLAG_LE_PGNO);
- } else if(sqlcipher_sqlite3StrICmp(zRight, "be") == 0) {
- sqlcipher_codec_ctx_unset_flag(ctx, CIPHER_FLAG_LE_PGNO);
- sqlcipher_codec_ctx_set_flag(ctx, CIPHER_FLAG_BE_PGNO);
- } else if(sqlcipher_sqlite3StrICmp(zRight, "native") == 0) {
- sqlcipher_codec_ctx_unset_flag(ctx, CIPHER_FLAG_LE_PGNO);
- sqlcipher_codec_ctx_unset_flag(ctx, CIPHER_FLAG_BE_PGNO);
- }
- codec_vdbe_return_string(pParse, "cipher_hmac_pgno", deprecation, P4_TRANSIENT);
- sqlcipher_sqlite3_log(SQLITE_WARNING, deprecation);
-
- } else {
- if(sqlcipher_codec_ctx_get_flag(ctx, CIPHER_FLAG_LE_PGNO)) {
- codec_vdbe_return_string(pParse, "cipher_hmac_pgno", "le", P4_TRANSIENT);
- } else if(sqlcipher_codec_ctx_get_flag(ctx, CIPHER_FLAG_BE_PGNO)) {
- codec_vdbe_return_string(pParse, "cipher_hmac_pgno", "be", P4_TRANSIENT);
- } else {
- codec_vdbe_return_string(pParse, "cipher_hmac_pgno", "native", P4_TRANSIENT);
- }
- }
- }
- }else
- if( sqlcipher_sqlite3StrICmp(zLeft,"cipher_hmac_salt_mask")==0 ){
- if(ctx) {
- if(zRight) {
- char *deprecation = "PRAGMA cipher_hmac_salt_mask is deprecated, please remove from use";
- if (sqlcipher_sqlite3StrNICmp(zRight ,"x'", 2) == 0 && sqlcipher_sqlite3Strlen30(zRight) == 5) {
- unsigned char mask = 0;
- const unsigned char *hex = (const unsigned char *)zRight+2;
- cipher_hex2bin(hex,2,&mask);
- sqlcipher_set_hmac_salt_mask(mask);
- }
- codec_vdbe_return_string(pParse, "cipher_hmac_salt_mask", deprecation, P4_TRANSIENT);
- sqlcipher_sqlite3_log(SQLITE_WARNING, deprecation);
- } else {
- char *hmac_salt_mask = sqlcipher_sqlite3_mprintf("%02x", sqlcipher_get_hmac_salt_mask());
- codec_vdbe_return_string(pParse, "cipher_hmac_salt_mask", hmac_salt_mask, P4_DYNAMIC);
- }
- }
- }else
- if( sqlcipher_sqlite3StrICmp(zLeft,"cipher_plaintext_header_size")==0 ){
- if(ctx) {
- if( zRight ) {
- int size = atoi(zRight);
- /* deliberately ignore result code, if size is invalid it will be set to -1
- and trip the error later in the codec */
- sqlcipher_codec_ctx_set_plaintext_header_size(ctx, size);
- } else {
- char *size = sqlcipher_sqlite3_mprintf("%d", sqlcipher_codec_ctx_get_plaintext_header_size(ctx));
- codec_vdbe_return_string(pParse, "cipher_plaintext_header_size", size, P4_DYNAMIC);
- }
- }
- }else
- if( sqlcipher_sqlite3StrICmp(zLeft,"cipher_default_plaintext_header_size")==0 ){
- if( zRight ) {
- sqlcipher_set_default_plaintext_header_size(atoi(zRight));
- } else {
- char *size = sqlcipher_sqlite3_mprintf("%d", sqlcipher_get_default_plaintext_header_size());
- codec_vdbe_return_string(pParse, "cipher_default_plaintext_header_size", size, P4_DYNAMIC);
- }
- }else
- if( sqlcipher_sqlite3StrICmp(zLeft,"cipher_salt")==0 ){
- if(ctx) {
- if(zRight) {
- if (sqlcipher_sqlite3StrNICmp(zRight ,"x'", 2) == 0 && sqlcipher_sqlite3Strlen30(zRight) == (FILE_HEADER_SZ*2)+3) {
- unsigned char *salt = (unsigned char*) sqlcipher_sqlite3_malloc(FILE_HEADER_SZ);
- const unsigned char *hex = (const unsigned char *)zRight+2;
- cipher_hex2bin(hex,FILE_HEADER_SZ*2,salt);
- sqlcipher_codec_ctx_set_kdf_salt(ctx, salt, FILE_HEADER_SZ);
- sqlcipher_sqlite3_free(salt);
- }
- } else {
- void *salt;
- char *hexsalt = (char*) sqlcipher_sqlite3_malloc((FILE_HEADER_SZ*2)+1);
- if((rc = sqlcipher_codec_ctx_get_kdf_salt(ctx, &salt)) == SQLITE_OK) {
- cipher_bin2hex(salt, FILE_HEADER_SZ, hexsalt);
- codec_vdbe_return_string(pParse, "cipher_salt", hexsalt, P4_DYNAMIC);
- } else {
- sqlcipher_sqlite3_free(hexsalt);
- sqlcipher_codec_ctx_set_error(ctx, rc);
- }
- }
- }
- }else
- if( sqlcipher_sqlite3StrICmp(zLeft,"cipher_hmac_algorithm")==0 ){
- if(ctx) {
- if(zRight) {
- rc = SQLITE_ERROR;
- if(sqlcipher_sqlite3StrICmp(zRight, SQLCIPHER_HMAC_SHA1_LABEL) == 0) {
- rc = sqlcipher_codec_ctx_set_hmac_algorithm(ctx, SQLCIPHER_HMAC_SHA1);
- } else if(sqlcipher_sqlite3StrICmp(zRight, SQLCIPHER_HMAC_SHA256_LABEL) == 0) {
- rc = sqlcipher_codec_ctx_set_hmac_algorithm(ctx, SQLCIPHER_HMAC_SHA256);
- } else if(sqlcipher_sqlite3StrICmp(zRight, SQLCIPHER_HMAC_SHA512_LABEL) == 0) {
- rc = sqlcipher_codec_ctx_set_hmac_algorithm(ctx, SQLCIPHER_HMAC_SHA512);
- }
- if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
- rc = codec_set_btree_to_codec_pagesize(db, pDb, ctx);
- if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
- } else {
- int algorithm = sqlcipher_codec_ctx_get_hmac_algorithm(ctx);
- if(algorithm == SQLCIPHER_HMAC_SHA1) {
- codec_vdbe_return_string(pParse, "cipher_hmac_algorithm", SQLCIPHER_HMAC_SHA1_LABEL, P4_TRANSIENT);
- } else if(algorithm == SQLCIPHER_HMAC_SHA256) {
- codec_vdbe_return_string(pParse, "cipher_hmac_algorithm", SQLCIPHER_HMAC_SHA256_LABEL, P4_TRANSIENT);
- } else if(algorithm == SQLCIPHER_HMAC_SHA512) {
- codec_vdbe_return_string(pParse, "cipher_hmac_algorithm", SQLCIPHER_HMAC_SHA512_LABEL, P4_TRANSIENT);
- }
- }
- }
- }else
- if( sqlcipher_sqlite3StrICmp(zLeft,"cipher_default_hmac_algorithm")==0 ){
- if(zRight) {
- rc = SQLITE_ERROR;
- if(sqlcipher_sqlite3StrICmp(zRight, SQLCIPHER_HMAC_SHA1_LABEL) == 0) {
- rc = sqlcipher_set_default_hmac_algorithm(SQLCIPHER_HMAC_SHA1);
- } else if(sqlcipher_sqlite3StrICmp(zRight, SQLCIPHER_HMAC_SHA256_LABEL) == 0) {
- rc = sqlcipher_set_default_hmac_algorithm(SQLCIPHER_HMAC_SHA256);
- } else if(sqlcipher_sqlite3StrICmp(zRight, SQLCIPHER_HMAC_SHA512_LABEL) == 0) {
- rc = sqlcipher_set_default_hmac_algorithm(SQLCIPHER_HMAC_SHA512);
- }
- } else {
- int algorithm = sqlcipher_get_default_hmac_algorithm();
- if(algorithm == SQLCIPHER_HMAC_SHA1) {
- codec_vdbe_return_string(pParse, "cipher_default_hmac_algorithm", SQLCIPHER_HMAC_SHA1_LABEL, P4_TRANSIENT);
- } else if(algorithm == SQLCIPHER_HMAC_SHA256) {
- codec_vdbe_return_string(pParse, "cipher_default_hmac_algorithm", SQLCIPHER_HMAC_SHA256_LABEL, P4_TRANSIENT);
- } else if(algorithm == SQLCIPHER_HMAC_SHA512) {
- codec_vdbe_return_string(pParse, "cipher_default_hmac_algorithm", SQLCIPHER_HMAC_SHA512_LABEL, P4_TRANSIENT);
- }
- }
- }else
- if( sqlcipher_sqlite3StrICmp(zLeft,"cipher_kdf_algorithm")==0 ){
- if(ctx) {
- if(zRight) {
- rc = SQLITE_ERROR;
- if(sqlcipher_sqlite3StrICmp(zRight, SQLCIPHER_PBKDF2_HMAC_SHA1_LABEL) == 0) {
- rc = sqlcipher_codec_ctx_set_kdf_algorithm(ctx, SQLCIPHER_PBKDF2_HMAC_SHA1);
- } else if(sqlcipher_sqlite3StrICmp(zRight, SQLCIPHER_PBKDF2_HMAC_SHA256_LABEL) == 0) {
- rc = sqlcipher_codec_ctx_set_kdf_algorithm(ctx, SQLCIPHER_PBKDF2_HMAC_SHA256);
- } else if(sqlcipher_sqlite3StrICmp(zRight, SQLCIPHER_PBKDF2_HMAC_SHA512_LABEL) == 0) {
- rc = sqlcipher_codec_ctx_set_kdf_algorithm(ctx, SQLCIPHER_PBKDF2_HMAC_SHA512);
- }
- if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
- } else {
- int algorithm = sqlcipher_codec_ctx_get_kdf_algorithm(ctx);
- if(algorithm == SQLCIPHER_PBKDF2_HMAC_SHA1) {
- codec_vdbe_return_string(pParse, "cipher_kdf_algorithm", SQLCIPHER_PBKDF2_HMAC_SHA1_LABEL, P4_TRANSIENT);
- } else if(algorithm == SQLCIPHER_PBKDF2_HMAC_SHA256) {
- codec_vdbe_return_string(pParse, "cipher_kdf_algorithm", SQLCIPHER_PBKDF2_HMAC_SHA256_LABEL, P4_TRANSIENT);
- } else if(algorithm == SQLCIPHER_PBKDF2_HMAC_SHA512) {
- codec_vdbe_return_string(pParse, "cipher_kdf_algorithm", SQLCIPHER_PBKDF2_HMAC_SHA512_LABEL, P4_TRANSIENT);
- }
- }
- }
- }else
- if( sqlcipher_sqlite3StrICmp(zLeft,"cipher_default_kdf_algorithm")==0 ){
- if(zRight) {
- rc = SQLITE_ERROR;
- if(sqlcipher_sqlite3StrICmp(zRight, SQLCIPHER_PBKDF2_HMAC_SHA1_LABEL) == 0) {
- rc = sqlcipher_set_default_kdf_algorithm(SQLCIPHER_PBKDF2_HMAC_SHA1);
- } else if(sqlcipher_sqlite3StrICmp(zRight, SQLCIPHER_PBKDF2_HMAC_SHA256_LABEL) == 0) {
- rc = sqlcipher_set_default_kdf_algorithm(SQLCIPHER_PBKDF2_HMAC_SHA256);
- } else if(sqlcipher_sqlite3StrICmp(zRight, SQLCIPHER_PBKDF2_HMAC_SHA512_LABEL) == 0) {
- rc = sqlcipher_set_default_kdf_algorithm(SQLCIPHER_PBKDF2_HMAC_SHA512);
- }
- } else {
- int algorithm = sqlcipher_get_default_kdf_algorithm();
- if(algorithm == SQLCIPHER_PBKDF2_HMAC_SHA1) {
- codec_vdbe_return_string(pParse, "cipher_default_kdf_algorithm", SQLCIPHER_PBKDF2_HMAC_SHA1_LABEL, P4_TRANSIENT);
- } else if(algorithm == SQLCIPHER_PBKDF2_HMAC_SHA256) {
- codec_vdbe_return_string(pParse, "cipher_default_kdf_algorithm", SQLCIPHER_PBKDF2_HMAC_SHA256_LABEL, P4_TRANSIENT);
- } else if(algorithm == SQLCIPHER_PBKDF2_HMAC_SHA512) {
- codec_vdbe_return_string(pParse, "cipher_default_kdf_algorithm", SQLCIPHER_PBKDF2_HMAC_SHA512_LABEL, P4_TRANSIENT);
- }
- }
- }else
- if( sqlcipher_sqlite3StrICmp(zLeft,"cipher_compatibility")==0 ){
- if(ctx) {
- if(zRight) {
- int version = atoi(zRight);
-
- switch(version) {
- case 1:
- rc = sqlcipher_codec_ctx_set_pagesize(ctx, 1024);
- if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
- rc = sqlcipher_codec_ctx_set_hmac_algorithm(ctx, SQLCIPHER_HMAC_SHA1);
- if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
- rc = sqlcipher_codec_ctx_set_kdf_algorithm(ctx, SQLCIPHER_PBKDF2_HMAC_SHA1);
- if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
- rc = sqlcipher_codec_ctx_set_kdf_iter(ctx, 4000);
- if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
- rc = sqlcipher_codec_ctx_set_use_hmac(ctx, 0);
- if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
- break;
-
- case 2:
- rc = sqlcipher_codec_ctx_set_pagesize(ctx, 1024);
- if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
- rc = sqlcipher_codec_ctx_set_hmac_algorithm(ctx, SQLCIPHER_HMAC_SHA1);
- if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
- rc = sqlcipher_codec_ctx_set_kdf_algorithm(ctx, SQLCIPHER_PBKDF2_HMAC_SHA1);
- if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
- rc = sqlcipher_codec_ctx_set_kdf_iter(ctx, 4000);
- if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
- rc = sqlcipher_codec_ctx_set_use_hmac(ctx, 1);
- if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
- break;
-
- case 3:
- rc = sqlcipher_codec_ctx_set_pagesize(ctx, 1024);
- if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
- rc = sqlcipher_codec_ctx_set_hmac_algorithm(ctx, SQLCIPHER_HMAC_SHA1);
- if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
- rc = sqlcipher_codec_ctx_set_kdf_algorithm(ctx, SQLCIPHER_PBKDF2_HMAC_SHA1);
- if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
- rc = sqlcipher_codec_ctx_set_kdf_iter(ctx, 64000);
- if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
- rc = sqlcipher_codec_ctx_set_use_hmac(ctx, 1);
- if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
- break;
-
- default:
- rc = sqlcipher_codec_ctx_set_pagesize(ctx, 4096);
- if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
- rc = sqlcipher_codec_ctx_set_hmac_algorithm(ctx, SQLCIPHER_HMAC_SHA512);
- if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
- rc = sqlcipher_codec_ctx_set_kdf_algorithm(ctx, SQLCIPHER_PBKDF2_HMAC_SHA512);
- if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
- rc = sqlcipher_codec_ctx_set_kdf_iter(ctx, 256000);
- if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
- rc = sqlcipher_codec_ctx_set_use_hmac(ctx, 1);
- if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
- break;
- }
-
- rc = codec_set_btree_to_codec_pagesize(db, pDb, ctx);
- if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
- }
- }
- }else
- if( sqlcipher_sqlite3StrICmp(zLeft,"cipher_default_compatibility")==0 ){
- if(zRight) {
- int version = atoi(zRight);
- switch(version) {
- case 1:
- sqlcipher_set_default_pagesize(1024);
- sqlcipher_set_default_hmac_algorithm(SQLCIPHER_HMAC_SHA1);
- sqlcipher_set_default_kdf_algorithm(SQLCIPHER_PBKDF2_HMAC_SHA1);
- sqlcipher_set_default_kdf_iter(4000);
- sqlcipher_set_default_use_hmac(0);
- break;
-
- case 2:
- sqlcipher_set_default_pagesize(1024);
- sqlcipher_set_default_hmac_algorithm(SQLCIPHER_HMAC_SHA1);
- sqlcipher_set_default_kdf_algorithm(SQLCIPHER_PBKDF2_HMAC_SHA1);
- sqlcipher_set_default_kdf_iter(4000);
- sqlcipher_set_default_use_hmac(1);
- break;
-
- case 3:
- sqlcipher_set_default_pagesize(1024);
- sqlcipher_set_default_hmac_algorithm(SQLCIPHER_HMAC_SHA1);
- sqlcipher_set_default_kdf_algorithm(SQLCIPHER_PBKDF2_HMAC_SHA1);
- sqlcipher_set_default_kdf_iter(64000);
- sqlcipher_set_default_use_hmac(1);
- break;
-
- default:
- sqlcipher_set_default_pagesize(4096);
- sqlcipher_set_default_hmac_algorithm(SQLCIPHER_HMAC_SHA512);
- sqlcipher_set_default_kdf_algorithm(SQLCIPHER_PBKDF2_HMAC_SHA512);
- sqlcipher_set_default_kdf_iter(256000);
- sqlcipher_set_default_use_hmac(1);
- break;
- }
- }
- }else
- if( sqlcipher_sqlite3StrICmp(zLeft,"cipher_memory_security")==0 ){
- if( zRight ) {
- sqlcipher_set_mem_security(sqlcipher_sqlite3GetBoolean(zRight,1));
- } else {
- char *on = sqlcipher_sqlite3_mprintf("%d", sqlcipher_get_mem_security());
- codec_vdbe_return_string(pParse, "cipher_memory_security", on, P4_DYNAMIC);
- }
- }else
- if( sqlcipher_sqlite3StrICmp(zLeft,"cipher_settings")==0 ){
- if(ctx) {
- int algorithm;
- char *pragma;
-
- pragma = sqlcipher_sqlite3_mprintf("PRAGMA kdf_iter = %d;", sqlcipher_codec_ctx_get_kdf_iter(ctx));
- codec_vdbe_return_string(pParse, "pragma", pragma, P4_DYNAMIC);
-
- pragma = sqlcipher_sqlite3_mprintf("PRAGMA cipher_page_size = %d;", sqlcipher_codec_ctx_get_pagesize(ctx));
- codec_vdbe_return_string(pParse, "pragma", pragma, P4_DYNAMIC);
-
- pragma = sqlcipher_sqlite3_mprintf("PRAGMA cipher_use_hmac = %d;", sqlcipher_codec_ctx_get_use_hmac(ctx));
- codec_vdbe_return_string(pParse, "pragma", pragma, P4_DYNAMIC);
-
- pragma = sqlcipher_sqlite3_mprintf("PRAGMA cipher_plaintext_header_size = %d;", sqlcipher_codec_ctx_get_plaintext_header_size(ctx));
- codec_vdbe_return_string(pParse, "pragma", pragma, P4_DYNAMIC);
-
- algorithm = sqlcipher_codec_ctx_get_hmac_algorithm(ctx);
- pragma = NULL;
- if(algorithm == SQLCIPHER_HMAC_SHA1) {
- pragma = sqlcipher_sqlite3_mprintf("PRAGMA cipher_hmac_algorithm = %s;", SQLCIPHER_HMAC_SHA1_LABEL);
- } else if(algorithm == SQLCIPHER_HMAC_SHA256) {
- pragma = sqlcipher_sqlite3_mprintf("PRAGMA cipher_hmac_algorithm = %s;", SQLCIPHER_HMAC_SHA256_LABEL);
- } else if(algorithm == SQLCIPHER_HMAC_SHA512) {
- pragma = sqlcipher_sqlite3_mprintf("PRAGMA cipher_hmac_algorithm = %s;", SQLCIPHER_HMAC_SHA512_LABEL);
- }
- codec_vdbe_return_string(pParse, "pragma", pragma, P4_DYNAMIC);
-
- algorithm = sqlcipher_codec_ctx_get_kdf_algorithm(ctx);
- pragma = NULL;
- if(algorithm == SQLCIPHER_PBKDF2_HMAC_SHA1) {
- pragma = sqlcipher_sqlite3_mprintf("PRAGMA cipher_kdf_algorithm = %s;", SQLCIPHER_PBKDF2_HMAC_SHA1_LABEL);
- } else if(algorithm == SQLCIPHER_PBKDF2_HMAC_SHA256) {
- pragma = sqlcipher_sqlite3_mprintf("PRAGMA cipher_kdf_algorithm = %s;", SQLCIPHER_PBKDF2_HMAC_SHA256_LABEL);
- } else if(algorithm == SQLCIPHER_PBKDF2_HMAC_SHA512) {
- pragma = sqlcipher_sqlite3_mprintf("PRAGMA cipher_kdf_algorithm = %s;", SQLCIPHER_PBKDF2_HMAC_SHA512_LABEL);
- }
- codec_vdbe_return_string(pParse, "pragma", pragma, P4_DYNAMIC);
-
- }
- }else
- if( sqlcipher_sqlite3StrICmp(zLeft,"cipher_default_settings")==0 ){
- int algorithm;
- char *pragma;
-
- pragma = sqlcipher_sqlite3_mprintf("PRAGMA cipher_default_kdf_iter = %d;", sqlcipher_get_default_kdf_iter());
- codec_vdbe_return_string(pParse, "pragma", pragma, P4_DYNAMIC);
-
- pragma = sqlcipher_sqlite3_mprintf("PRAGMA cipher_default_page_size = %d;", sqlcipher_get_default_pagesize());
- codec_vdbe_return_string(pParse, "pragma", pragma, P4_DYNAMIC);
-
- pragma = sqlcipher_sqlite3_mprintf("PRAGMA cipher_default_use_hmac = %d;", sqlcipher_get_default_use_hmac());
- codec_vdbe_return_string(pParse, "pragma", pragma, P4_DYNAMIC);
-
- pragma = sqlcipher_sqlite3_mprintf("PRAGMA cipher_default_plaintext_header_size = %d;", sqlcipher_get_default_plaintext_header_size());
- codec_vdbe_return_string(pParse, "pragma", pragma, P4_DYNAMIC);
-
- algorithm = sqlcipher_get_default_hmac_algorithm();
- pragma = NULL;
- if(algorithm == SQLCIPHER_HMAC_SHA1) {
- pragma = sqlcipher_sqlite3_mprintf("PRAGMA cipher_default_hmac_algorithm = %s;", SQLCIPHER_HMAC_SHA1_LABEL);
- } else if(algorithm == SQLCIPHER_HMAC_SHA256) {
- pragma = sqlcipher_sqlite3_mprintf("PRAGMA cipher_default_hmac_algorithm = %s;", SQLCIPHER_HMAC_SHA256_LABEL);
- } else if(algorithm == SQLCIPHER_HMAC_SHA512) {
- pragma = sqlcipher_sqlite3_mprintf("PRAGMA cipher_default_hmac_algorithm = %s;", SQLCIPHER_HMAC_SHA512_LABEL);
- }
- codec_vdbe_return_string(pParse, "pragma", pragma, P4_DYNAMIC);
-
- algorithm = sqlcipher_get_default_kdf_algorithm();
- pragma = NULL;
- if(algorithm == SQLCIPHER_PBKDF2_HMAC_SHA1) {
- pragma = sqlcipher_sqlite3_mprintf("PRAGMA cipher_default_kdf_algorithm = %s;", SQLCIPHER_PBKDF2_HMAC_SHA1_LABEL);
- } else if(algorithm == SQLCIPHER_PBKDF2_HMAC_SHA256) {
- pragma = sqlcipher_sqlite3_mprintf("PRAGMA cipher_default_kdf_algorithm = %s;", SQLCIPHER_PBKDF2_HMAC_SHA256_LABEL);
- } else if(algorithm == SQLCIPHER_PBKDF2_HMAC_SHA512) {
- pragma = sqlcipher_sqlite3_mprintf("PRAGMA cipher_default_kdf_algorithm = %s;", SQLCIPHER_PBKDF2_HMAC_SHA512_LABEL);
- }
- codec_vdbe_return_string(pParse, "pragma", pragma, P4_DYNAMIC);
- }else
- if( sqlcipher_sqlite3StrICmp(zLeft,"cipher_integrity_check")==0 ){
- if(ctx) {
- sqlcipher_codec_ctx_integrity_check(ctx, pParse, "cipher_integrity_check");
- }
- }else {
- return 0;
- }
- return 1;
-}
-
-/* these constants are used internally within SQLite's pager.c to differentiate between
- operations on the main database or journal pages. This is important in the context
- of a rekey operations, where the journal must be written using the original key
- material (to allow a transactional rollback), while the new database pages are being
- written with the new key material*/
-#define CODEC_READ_OP 3
-#define CODEC_WRITE_OP 6
-#define CODEC_JOURNAL_OP 7
-
-/*
- * sqlcipher_sqlite3Codec can be called in multiple modes.
- * encrypt mode - expected to return a pointer to the
- * encrypted data without altering pData.
- * decrypt mode - expected to return a pointer to pData, with
- * the data decrypted in the input buffer
- */
-static void* sqlcipher_sqlite3Codec(void *iCtx, void *data, Pgno pgno, int mode) {
- codec_ctx *ctx = (codec_ctx *) iCtx;
- int offset = 0, rc = 0;
- int page_sz = sqlcipher_codec_ctx_get_pagesize(ctx);
- unsigned char *pData = (unsigned char *) data;
- void *buffer = sqlcipher_codec_ctx_get_data(ctx);
- int plaintext_header_sz = sqlcipher_codec_ctx_get_plaintext_header_size(ctx);
- int cctx = CIPHER_READ_CTX;
-
- CODEC_TRACE("sqlcipher_sqlite3Codec: entered pgno=%d, mode=%d, page_sz=%d\n", pgno, mode, page_sz);
-
-#ifdef SQLCIPHER_EXT
- if(sqlcipher_license_check(ctx) != SQLITE_OK) return NULL;
+#ifdef SQLITE_DEFAULT_LOOKASIDE
+ "DEFAULT_LOOKASIDE=" CTIMEOPT_VAL2(SQLITE_DEFAULT_LOOKASIDE),
#endif
-
- /* call to derive keys if not present yet */
- if((rc = sqlcipher_codec_key_derive(ctx)) != SQLITE_OK) {
- sqlcipher_codec_ctx_set_error(ctx, rc);
- return NULL;
- }
-
- /* if the plaintext_header_size is negative that means an invalid size was set via
- PRAGMA. We can't set the error state on the pager at that point because the pager
- may not be open yet. However, this is a fatal error state, so abort the codec */
- if(plaintext_header_sz < 0) {
- sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
- return NULL;
- }
-
- if(pgno == 1) /* adjust starting pointers in data page for header offset on first page*/
- offset = plaintext_header_sz ? plaintext_header_sz : FILE_HEADER_SZ;
-
-
- CODEC_TRACE("sqlcipher_sqlite3Codec: switch mode=%d offset=%d\n", mode, offset);
- switch(mode) {
- case CODEC_READ_OP: /* decrypt */
- if(pgno == 1) /* copy initial part of file header or SQLite magic to buffer */
- memcpy(buffer, plaintext_header_sz ? pData : (void *) SQLITE_FILE_HEADER, offset);
-
- rc = sqlcipher_page_cipher(ctx, cctx, pgno, CIPHER_DECRYPT, page_sz - offset, pData + offset, (unsigned char*)buffer + offset);
-#ifdef SQLCIPHER_TEST
- if(cipher_fail_next_decrypt) rc = SQLITE_ERROR;
+#ifdef SQLITE_DEFAULT_MEMSTATUS
+# if SQLITE_DEFAULT_MEMSTATUS != 1
+ "DEFAULT_MEMSTATUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_MEMSTATUS),
+# endif
#endif
- if(rc != SQLITE_OK) { /* clear results of failed cipher operation and set error */
- sqlcipher_memset((unsigned char*) buffer+offset, 0, page_sz-offset);
- sqlcipher_codec_ctx_set_error(ctx, rc);
- }
- memcpy(pData, buffer, page_sz); /* copy buffer data back to pData and return */
- return pData;
- break;
-
- case CODEC_WRITE_OP: /* encrypt database page, operate on write context and fall through to case 7, so the write context is used*/
- cctx = CIPHER_WRITE_CTX;
-
- case CODEC_JOURNAL_OP: /* encrypt journal page, operate on read context use to get the original page data from the database */
- if(pgno == 1) { /* copy initial part of file header or salt to buffer */
- void *kdf_salt = NULL;
- /* retrieve the kdf salt */
- if((rc = sqlcipher_codec_ctx_get_kdf_salt(ctx, &kdf_salt)) != SQLITE_OK) {
- sqlcipher_codec_ctx_set_error(ctx, rc);
- return NULL;
- }
- memcpy(buffer, plaintext_header_sz ? pData : kdf_salt, offset);
- }
- rc = sqlcipher_page_cipher(ctx, cctx, pgno, CIPHER_ENCRYPT, page_sz - offset, pData + offset, (unsigned char*)buffer + offset);
-#ifdef SQLCIPHER_TEST
- if(cipher_fail_next_encrypt) rc = SQLITE_ERROR;
+#ifdef SQLITE_DEFAULT_MMAP_SIZE
+ "DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE),
#endif
- if(rc != SQLITE_OK) { /* clear results of failed cipher operation and set error */
- sqlcipher_memset((unsigned char*)buffer+offset, 0, page_sz-offset);
- sqlcipher_codec_ctx_set_error(ctx, rc);
- return NULL;
- }
- return buffer; /* return persistent buffer data, pData remains intact */
- break;
-
- default:
- sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR); /* unsupported mode, set error */
- return pData;
- break;
- }
-}
-
-static void sqlcipher_sqlite3FreeCodecArg(void *pCodecArg) {
- codec_ctx *ctx = (codec_ctx *) pCodecArg;
- if(pCodecArg == NULL) return;
- sqlcipher_codec_ctx_free(&ctx); /* wipe and free allocated memory for the context */
- sqlcipher_deactivate(); /* cleanup related structures, OpenSSL etc, when codec is detatched */
-}
-
-SQLITE_PRIVATE int sqlcipher_sqlite3CodecAttach(sqlcipher_sqlite3* db, int nDb, const void *zKey, int nKey) {
- struct Db *pDb = &db->aDb[nDb];
-
- CODEC_TRACE("sqlcipher_sqlite3CodecAttach: entered db=%p, nDb=%d zKey=%s, nKey=%d\n", db, nDb, (char *)zKey, nKey);
-
-
- if(nKey && zKey && pDb->pBt) {
- int rc;
- Pager *pPager = pDb->pBt->pBt->pPager;
- sqlcipher_sqlite3_file *fd;
- codec_ctx *ctx;
-
- /* check if the sqlcipher_sqlite3_file is open, and if not force handle to NULL */
- if((fd = sqlcipher_sqlite3PagerFile(pPager))->pMethods == 0) fd = NULL;
-
- CODEC_TRACE("sqlcipher_sqlite3CodecAttach: calling sqlcipher_activate()\n");
- sqlcipher_activate(); /* perform internal initialization for sqlcipher */
-
- CODEC_TRACE_MUTEX("sqlcipher_sqlite3CodecAttach: entering database mutex %p\n", db->mutex);
- sqlcipher_sqlite3_mutex_enter(db->mutex);
- CODEC_TRACE_MUTEX("sqlcipher_sqlite3CodecAttach: entered database mutex %p\n", db->mutex);
-
-#ifdef SQLCIPHER_EXT
- if((rc = sqlcipher_sqlite3_set_authorizer(db, sqlcipher_license_authorizer, db)) != SQLITE_OK) {
- sqlcipher_sqlite3_mutex_leave(db->mutex);
- return rc;
- }
+#ifdef SQLITE_DEFAULT_PAGE_SIZE
+ "DEFAULT_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_PAGE_SIZE),
#endif
-
- /* point the internal codec argument against the contet to be prepared */
- CODEC_TRACE("sqlcipher_sqlite3CodecAttach: calling sqlcipher_codec_ctx_init()\n");
- rc = sqlcipher_codec_ctx_init(&ctx, pDb, pDb->pBt->pBt->pPager, zKey, nKey);
-
- if(rc != SQLITE_OK) {
- /* initialization failed, do not attach potentially corrupted context */
- CODEC_TRACE("sqlcipher_sqlite3CodecAttach: context initialization failed with rc=%d\n", rc);
- /* force an error at the pager level, such that even the upstream caller ignores the return code
- the pager will be in an error state and will process no further operations */
- sqlcipher_sqlite3pager_error(pPager, rc);
- pDb->pBt->pBt->db->errCode = rc;
- CODEC_TRACE_MUTEX("sqlcipher_sqlite3CodecAttach: leaving database mutex %p (early return on rc=%d)\n", db->mutex, rc);
- sqlcipher_sqlite3_mutex_leave(db->mutex);
- CODEC_TRACE_MUTEX("sqlcipher_sqlite3CodecAttach: left database mutex %p (early return on rc=%d)\n", db->mutex, rc);
- return rc;
- }
-
- CODEC_TRACE("sqlcipher_sqlite3CodecAttach: calling sqlcipher_sqlite3PagerSetCodec()\n");
- sqlcipher_sqlite3PagerSetCodec(sqlcipher_sqlite3BtreePager(pDb->pBt), sqlcipher_sqlite3Codec, NULL, sqlcipher_sqlite3FreeCodecArg, (void *) ctx);
-
- CODEC_TRACE("sqlcipher_sqlite3CodecAttach: calling codec_set_btree_to_codec_pagesize()\n");
- codec_set_btree_to_codec_pagesize(db, pDb, ctx);
-
- /* force secure delete. This has the benefit of wiping internal data when deleted
- and also ensures that all pages are written to disk (i.e. not skipped by
- sqlcipher_sqlite3PagerDontWrite optimizations) */
- CODEC_TRACE("sqlcipher_sqlite3CodecAttach: calling sqlcipher_sqlite3BtreeSecureDelete()\n");
- sqlcipher_sqlite3BtreeSecureDelete(pDb->pBt, 1);
-
- /* if fd is null, then this is an in-memory database and
- we dont' want to overwrite the AutoVacuum settings
- if not null, then set to the default */
- if(fd != NULL) {
- CODEC_TRACE("sqlcipher_sqlite3CodecAttach: calling sqlcipher_sqlite3BtreeSetAutoVacuum()\n");
- sqlcipher_sqlite3BtreeSetAutoVacuum(pDb->pBt, SQLITE_DEFAULT_AUTOVACUUM);
- }
- CODEC_TRACE_MUTEX("sqlcipher_sqlite3CodecAttach: leaving database mutex %p\n", db->mutex);
- sqlcipher_sqlite3_mutex_leave(db->mutex);
- CODEC_TRACE_MUTEX("sqlcipher_sqlite3CodecAttach: left database mutex %p\n", db->mutex);
- }
- return SQLITE_OK;
-}
-
-int sqlcipher_find_db_index(sqlcipher_sqlite3 *db, const char *zDb) {
- int db_index;
- if(zDb == NULL){
- return 0;
- }
- for(db_index = 0; db_index < db->nDb; db_index++) {
- struct Db *pDb = &db->aDb[db_index];
- if(strcmp(pDb->zDbSName, zDb) == 0) {
- return db_index;
- }
- }
- return 0;
-}
-
-SQLITE_API void sqlcipher_sqlite3_activate_see(const char* in) {
- /* do nothing, security enhancements are always active */
-}
-
-SQLITE_API int sqlcipher_sqlite3_key(sqlcipher_sqlite3 *db, const void *pKey, int nKey) {
- CODEC_TRACE("sqlcipher_sqlite3_key entered: db=%p pKey=%s nKey=%d\n", db, (char *)pKey, nKey);
- return sqlcipher_sqlite3_key_v2(db, "main", pKey, nKey);
-}
-
-SQLITE_API int sqlcipher_sqlite3_key_v2(sqlcipher_sqlite3 *db, const char *zDb, const void *pKey, int nKey) {
- CODEC_TRACE("sqlcipher_sqlite3_key_v2: entered db=%p zDb=%s pKey=%s nKey=%d\n", db, zDb, (char *)pKey, nKey);
- /* attach key if db and pKey are not null and nKey is > 0 */
- if(db && pKey && nKey) {
- int db_index = sqlcipher_find_db_index(db, zDb);
- return sqlcipher_sqlite3CodecAttach(db, db_index, pKey, nKey);
- }
- return SQLITE_ERROR;
-}
-
-SQLITE_API int sqlcipher_sqlite3_rekey(sqlcipher_sqlite3 *db, const void *pKey, int nKey) {
- CODEC_TRACE("sqlcipher_sqlite3_rekey entered: db=%p pKey=%s nKey=%d\n", db, (char *)pKey, nKey);
- return sqlcipher_sqlite3_rekey_v2(db, "main", pKey, nKey);
-}
-
-/* sqlcipher_sqlite3_rekey_v2
-** Given a database, this will reencrypt the database using a new key.
-** There is only one possible modes of operation - to encrypt a database
-** that is already encrpyted. If the database is not already encrypted
-** this should do nothing
-** The proposed logic for this function follows:
-** 1. Determine if the database is already encryptped
-** 2. If there is NOT already a key present do nothing
-** 3. If there is a key present, re-encrypt the database with the new key
-*/
-SQLITE_API int sqlcipher_sqlite3_rekey_v2(sqlcipher_sqlite3 *db, const char *zDb, const void *pKey, int nKey) {
- CODEC_TRACE("sqlcipher_sqlite3_rekey_v2: entered db=%p zDb=%s pKey=%s, nKey=%d\n", db, zDb, (char *)pKey, nKey);
- if(db && pKey && nKey) {
- int db_index = sqlcipher_find_db_index(db, zDb);
- struct Db *pDb = &db->aDb[db_index];
- CODEC_TRACE("sqlcipher_sqlite3_rekey_v2: database pDb=%p db_index:%d\n", pDb, db_index);
- if(pDb->pBt) {
- codec_ctx *ctx;
- int rc, page_count;
- Pgno pgno;
- PgHdr *page;
- Pager *pPager = pDb->pBt->pBt->pPager;
-
- ctx = (codec_ctx*) sqlcipher_sqlite3PagerGetCodec(pDb->pBt->pBt->pPager);
-
- if(ctx == NULL) {
- /* there was no codec attached to this database, so this should do nothing! */
- CODEC_TRACE("sqlcipher_sqlite3_rekey_v2: no codec attached to db, exiting\n");
- return SQLITE_OK;
- }
-
- CODEC_TRACE_MUTEX("sqlcipher_sqlite3_rekey_v2: entering database mutex %p\n", db->mutex);
- sqlcipher_sqlite3_mutex_enter(db->mutex);
- CODEC_TRACE_MUTEX("sqlcipher_sqlite3_rekey_v2: entered database mutex %p\n", db->mutex);
-
- codec_set_pass_key(db, db_index, pKey, nKey, CIPHER_WRITE_CTX);
-
- /* do stuff here to rewrite the database
- ** 1. Create a transaction on the database
- ** 2. Iterate through each page, reading it and then writing it.
- ** 3. If that goes ok then commit and put ctx->rekey into ctx->key
- ** note: don't deallocate rekey since it may be used in a subsequent iteration
- */
- rc = sqlcipher_sqlite3BtreeBeginTrans(pDb->pBt, 1, 0); /* begin write transaction */
- sqlcipher_sqlite3PagerPagecount(pPager, &page_count);
- for(pgno = 1; rc == SQLITE_OK && pgno <= (unsigned int)page_count; pgno++) { /* pgno's start at 1 see pager.c:pagerAcquire */
- if(!sqlcipher_sqlite3pager_is_mj_pgno(pPager, pgno)) { /* skip this page (see pager.c:pagerAcquire for reasoning) */
- rc = sqlcipher_sqlite3PagerGet(pPager, pgno, &page, 0);
- if(rc == SQLITE_OK) { /* write page see pager_incr_changecounter for example */
- rc = sqlcipher_sqlite3PagerWrite(page);
- if(rc == SQLITE_OK) {
- sqlcipher_sqlite3PagerUnref(page);
- } else {
- CODEC_TRACE("sqlcipher_sqlite3_rekey_v2: error %d occurred writing page %d\n", rc, pgno);
- }
- } else {
- CODEC_TRACE("sqlcipher_sqlite3_rekey_v2: error %d occurred getting page %d\n", rc, pgno);
- }
- }
- }
-
- /* if commit was successful commit and copy the rekey data to current key, else rollback to release locks */
- if(rc == SQLITE_OK) {
- CODEC_TRACE("sqlcipher_sqlite3_rekey_v2: committing\n");
- rc = sqlcipher_sqlite3BtreeCommit(pDb->pBt);
- sqlcipher_codec_key_copy(ctx, CIPHER_WRITE_CTX);
- } else {
- CODEC_TRACE("sqlcipher_sqlite3_rekey_v2: rollback\n");
- sqlcipher_sqlite3BtreeRollback(pDb->pBt, SQLITE_ABORT_ROLLBACK, 0);
- }
-
- CODEC_TRACE_MUTEX("sqlcipher_sqlite3_rekey_v2: leaving database mutex %p\n", db->mutex);
- sqlcipher_sqlite3_mutex_leave(db->mutex);
- CODEC_TRACE_MUTEX("sqlcipher_sqlite3_rekey_v2: left database mutex %p\n", db->mutex);
- }
- return SQLITE_OK;
- }
- return SQLITE_ERROR;
-}
-
-SQLITE_PRIVATE void sqlcipher_sqlite3CodecGetKey(sqlcipher_sqlite3* db, int nDb, void **zKey, int *nKey) {
- struct Db *pDb = &db->aDb[nDb];
- CODEC_TRACE("sqlcipher_sqlite3CodecGetKey: entered db=%p, nDb=%d\n", db, nDb);
- if( pDb->pBt ) {
- codec_ctx *ctx = (codec_ctx*) sqlcipher_sqlite3PagerGetCodec(pDb->pBt->pBt->pPager);
-
- if(ctx) {
- /* pass back the keyspec from the codec, unless PRAGMA cipher_store_pass
- is set or keyspec has not yet been derived, in which case pass
- back the password key material */
- sqlcipher_codec_get_keyspec(ctx, zKey, nKey);
- if(sqlcipher_codec_get_store_pass(ctx) == 1 || *zKey == NULL) {
- sqlcipher_codec_get_pass(ctx, zKey, nKey);
- }
- } else {
- *zKey = NULL;
- *nKey = 0;
- }
- }
-}
-
-/*
- * Implementation of an "export" function that allows a caller
- * to duplicate the main database to an attached database. This is intended
- * as a conveneince for users who need to:
- *
- * 1. migrate from an non-encrypted database to an encrypted database
- * 2. move from an encrypted database to a non-encrypted database
- * 3. convert beween the various flavors of encrypted databases.
- *
- * This implementation is based heavily on the procedure and code used
- * in vacuum.c, but is exposed as a function that allows export to any
- * named attached database.
- */
-
-/*
-** Finalize a prepared statement. If there was an error, store the
-** text of the error message in *pzErrMsg. Return the result code.
-**
-** Based on vacuumFinalize from vacuum.c
-*/
-static int sqlcipher_finalize(sqlcipher_sqlite3 *db, sqlcipher_sqlite3_stmt *pStmt, char **pzErrMsg){
- int rc;
- rc = sqlcipher_sqlite3VdbeFinalize((Vdbe*)pStmt);
- if( rc ){
- sqlcipher_sqlite3SetString(pzErrMsg, db, sqlcipher_sqlite3_errmsg(db));
- }
- return rc;
-}
-
-/*
-** Execute zSql on database db. Return an error code.
-**
-** Based on execSql from vacuum.c
-*/
-static int sqlcipher_execSql(sqlcipher_sqlite3 *db, char **pzErrMsg, const char *zSql){
- sqlcipher_sqlite3_stmt *pStmt;
- VVA_ONLY( int rc; )
- if( !zSql ){
- return SQLITE_NOMEM;
- }
- if( SQLITE_OK!=sqlcipher_sqlite3_prepare(db, zSql, -1, &pStmt, 0) ){
- sqlcipher_sqlite3SetString(pzErrMsg, db, sqlcipher_sqlite3_errmsg(db));
- return sqlcipher_sqlite3_errcode(db);
- }
- VVA_ONLY( rc = ) sqlcipher_sqlite3_step(pStmt);
- assert( rc!=SQLITE_ROW );
- return sqlcipher_finalize(db, pStmt, pzErrMsg);
-}
-
-/*
-** Execute zSql on database db. The statement returns exactly
-** one column. Execute this as SQL on the same database.
-**
-** Based on execExecSql from vacuum.c
-*/
-static int sqlcipher_execExecSql(sqlcipher_sqlite3 *db, char **pzErrMsg, const char *zSql){
- sqlcipher_sqlite3_stmt *pStmt;
- int rc;
-
- rc = sqlcipher_sqlite3_prepare(db, zSql, -1, &pStmt, 0);
- if( rc!=SQLITE_OK ) return rc;
-
- while( SQLITE_ROW==sqlcipher_sqlite3_step(pStmt) ){
- rc = sqlcipher_execSql(db, pzErrMsg, (char*)sqlcipher_sqlite3_column_text(pStmt, 0));
- if( rc!=SQLITE_OK ){
- sqlcipher_finalize(db, pStmt, pzErrMsg);
- return rc;
- }
- }
-
- return sqlcipher_finalize(db, pStmt, pzErrMsg);
-}
-
-/*
- * copy database and schema from the main database to an attached database
- *
- * Based on sqlcipher_sqlite3RunVacuum from vacuum.c
-*/
-void sqlcipher_exportFunc(sqlcipher_sqlite3_context *context, int argc, sqlcipher_sqlite3_value **argv) {
- sqlcipher_sqlite3 *db = sqlcipher_sqlite3_context_db_handle(context);
- const char* targetDb, *sourceDb;
- int targetDb_idx = 0;
- u64 saved_flags = db->flags; /* Saved value of the db->flags */
- u32 saved_mDbFlags = db->mDbFlags; /* Saved value of the db->mDbFlags */
- int saved_nChange = db->nChange; /* Saved value of db->nChange */
- int saved_nTotalChange = db->nTotalChange; /* Saved value of db->nTotalChange */
- u8 saved_mTrace = db->mTrace; /* Saved value of db->mTrace */
- int rc = SQLITE_OK; /* Return code from service routines */
- char *zSql = NULL; /* SQL statements */
- char *pzErrMsg = NULL;
-
- if(argc != 1 && argc != 2) {
- rc = SQLITE_ERROR;
- pzErrMsg = sqlcipher_sqlite3_mprintf("invalid number of arguments (%d) passed to sqlcipher_export", argc);
- goto end_of_export;
- }
-
- if(sqlcipher_sqlite3_value_type(argv[0]) == SQLITE_NULL) {
- rc = SQLITE_ERROR;
- pzErrMsg = sqlcipher_sqlite3_mprintf("target database can't be NULL");
- goto end_of_export;
- }
-
- targetDb = (const char*) sqlcipher_sqlite3_value_text(argv[0]);
- sourceDb = "main";
-
- if(argc == 2) {
- if(sqlcipher_sqlite3_value_type(argv[1]) == SQLITE_NULL) {
- rc = SQLITE_ERROR;
- pzErrMsg = sqlcipher_sqlite3_mprintf("target database can't be NULL");
- goto end_of_export;
- }
- sourceDb = (char *) sqlcipher_sqlite3_value_text(argv[1]);
- }
-
-
- /* if the name of the target is not main, but the index returned is zero
- there is a mismatch and we should not proceed */
- targetDb_idx = sqlcipher_find_db_index(db, targetDb);
- if(targetDb_idx == 0 && targetDb != NULL && sqlcipher_sqlite3StrICmp("main", targetDb) != 0) {
- rc = SQLITE_ERROR;
- pzErrMsg = sqlcipher_sqlite3_mprintf("unknown database %s", targetDb);
- goto end_of_export;
- }
- db->init.iDb = targetDb_idx;
-
- db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks;
- db->mDbFlags |= DBFLAG_PreferBuiltin | DBFLAG_Vacuum;
- db->flags &= ~(u64)(SQLITE_ForeignKeys | SQLITE_ReverseOrder | SQLITE_Defensive | SQLITE_CountRows);
- db->mTrace = 0;
-
- /* Query the schema of the main database. Create a mirror schema
- ** in the temporary database.
- */
- zSql = sqlcipher_sqlite3_mprintf(
- "SELECT sql "
- " FROM %s.sqlite_schema WHERE type='table' AND name!='sqlite_sequence'"
- " AND rootpage>0"
- , sourceDb);
- rc = (zSql == NULL) ? SQLITE_NOMEM : sqlcipher_execExecSql(db, &pzErrMsg, zSql);
- if( rc!=SQLITE_OK ) goto end_of_export;
- sqlcipher_sqlite3_free(zSql);
-
- zSql = sqlcipher_sqlite3_mprintf(
- "SELECT sql "
- " FROM %s.sqlite_schema WHERE sql LIKE 'CREATE INDEX %%' "
- , sourceDb);
- rc = (zSql == NULL) ? SQLITE_NOMEM : sqlcipher_execExecSql(db, &pzErrMsg, zSql);
- if( rc!=SQLITE_OK ) goto end_of_export;
- sqlcipher_sqlite3_free(zSql);
-
- zSql = sqlcipher_sqlite3_mprintf(
- "SELECT sql "
- " FROM %s.sqlite_schema WHERE sql LIKE 'CREATE UNIQUE INDEX %%'"
- , sourceDb);
- rc = (zSql == NULL) ? SQLITE_NOMEM : sqlcipher_execExecSql(db, &pzErrMsg, zSql);
- if( rc!=SQLITE_OK ) goto end_of_export;
- sqlcipher_sqlite3_free(zSql);
-
- /* Loop through the tables in the main database. For each, do
- ** an "INSERT INTO rekey_db.xxx SELECT * FROM main.xxx;" to copy
- ** the contents to the temporary database.
- */
- zSql = sqlcipher_sqlite3_mprintf(
- "SELECT 'INSERT INTO %s.' || quote(name) "
- "|| ' SELECT * FROM %s.' || quote(name) || ';'"
- "FROM %s.sqlite_schema "
- "WHERE type = 'table' AND name!='sqlite_sequence' "
- " AND rootpage>0"
- , targetDb, sourceDb, sourceDb);
- rc = (zSql == NULL) ? SQLITE_NOMEM : sqlcipher_execExecSql(db, &pzErrMsg, zSql);
- if( rc!=SQLITE_OK ) goto end_of_export;
- sqlcipher_sqlite3_free(zSql);
-
- /* Copy over the contents of the sequence table
- */
- zSql = sqlcipher_sqlite3_mprintf(
- "SELECT 'INSERT INTO %s.' || quote(name) "
- "|| ' SELECT * FROM %s.' || quote(name) || ';' "
- "FROM %s.sqlite_schema WHERE name=='sqlite_sequence';"
- , targetDb, sourceDb, targetDb);
- rc = (zSql == NULL) ? SQLITE_NOMEM : sqlcipher_execExecSql(db, &pzErrMsg, zSql);
- if( rc!=SQLITE_OK ) goto end_of_export;
- sqlcipher_sqlite3_free(zSql);
-
- /* Copy the triggers, views, and virtual tables from the main database
- ** over to the temporary database. None of these objects has any
- ** associated storage, so all we have to do is copy their entries
- ** from the SQLITE_MASTER table.
- */
- zSql = sqlcipher_sqlite3_mprintf(
- "INSERT INTO %s.sqlite_schema "
- " SELECT type, name, tbl_name, rootpage, sql"
- " FROM %s.sqlite_schema"
- " WHERE type='view' OR type='trigger'"
- " OR (type='table' AND rootpage=0)"
- , targetDb, sourceDb);
- rc = (zSql == NULL) ? SQLITE_NOMEM : sqlcipher_execSql(db, &pzErrMsg, zSql);
- if( rc!=SQLITE_OK ) goto end_of_export;
- sqlcipher_sqlite3_free(zSql);
-
- zSql = NULL;
-end_of_export:
- db->init.iDb = 0;
- db->flags = saved_flags;
- db->mDbFlags = saved_mDbFlags;
- db->nChange = saved_nChange;
- db->nTotalChange = saved_nTotalChange;
- db->mTrace = saved_mTrace;
-
- if(zSql) sqlcipher_sqlite3_free(zSql);
-
- if(rc) {
- if(pzErrMsg != NULL) {
- sqlcipher_sqlite3_result_error(context, pzErrMsg, -1);
- sqlcipher_sqlite3DbFree(db, pzErrMsg);
- } else {
- sqlcipher_sqlite3_result_error(context, sqlcipher_sqlite3ErrStr(rc), -1);
- }
- }
-}
+#ifdef SQLITE_DEFAULT_PCACHE_INITSZ
+ "DEFAULT_PCACHE_INITSZ=" CTIMEOPT_VAL(SQLITE_DEFAULT_PCACHE_INITSZ),
#endif
-/* END SQLCIPHER */
-
-/************** End of crypto.c **********************************************/
-/************** Begin file crypto_impl.c *************************************/
-/*
-** SQLCipher
-** http://sqlcipher.net
-**
-** Copyright (c) 2008 - 2013, ZETETIC LLC
-** All rights reserved.
-**
-** Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in the
-** documentation and/or other materials provided with the distribution.
-** * Neither the name of the ZETETIC LLC nor the
-** names of its contributors may be used to endorse or promote products
-** derived from this software without specific prior written permission.
-**
-** THIS SOFTWARE IS PROVIDED BY ZETETIC LLC ''AS IS'' AND ANY
-** EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-** DISCLAIMED. IN NO EVENT SHALL ZETETIC LLC BE LIABLE FOR ANY
-** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-**
-*/
-/* BEGIN SQLCIPHER */
-#ifdef SQLITE_HAS_CODEC
-
-/* #include "sqlcipher.h" */
-/* #include "crypto.h" */
-#ifndef OMIT_MEMLOCK
-#if defined(__unix__) || defined(__APPLE__) || defined(_AIX)
-#include <errno.h>
-#include <unistd.h>
-#include <sys/resource.h>
-#include <sys/mman.h>
-#elif defined(_WIN32)
-#include <windows.h>
+#ifdef SQLITE_DEFAULT_PROXYDIR_PERMISSIONS
+ "DEFAULT_PROXYDIR_PERMISSIONS=" CTIMEOPT_VAL(SQLITE_DEFAULT_PROXYDIR_PERMISSIONS),
#endif
+#ifdef SQLITE_DEFAULT_RECURSIVE_TRIGGERS
+ "DEFAULT_RECURSIVE_TRIGGERS",
#endif
-
-static volatile unsigned int default_flags = DEFAULT_CIPHER_FLAGS;
-static volatile unsigned char hmac_salt_mask = HMAC_SALT_MASK;
-static volatile int default_kdf_iter = PBKDF2_ITER;
-static volatile int default_page_size = 4096;
-static volatile int default_plaintext_header_sz = 0;
-static volatile int default_hmac_algorithm = SQLCIPHER_HMAC_SHA512;
-static volatile int default_kdf_algorithm = SQLCIPHER_PBKDF2_HMAC_SHA512;
-static volatile int mem_security_on = 1;
-static volatile int mem_security_initialized = 0;
-static volatile int mem_security_activated = 0;
-static volatile unsigned int sqlcipher_activate_count = 0;
-static volatile sqlcipher_sqlite3_mem_methods default_mem_methods;
-static sqlcipher_provider *default_provider = NULL;
-
-static sqlcipher_sqlite3_mutex* sqlcipher_static_mutex[SQLCIPHER_MUTEX_COUNT];
-
-sqlcipher_sqlite3_mutex* sqlcipher_mutex(int mutex) {
- if(mutex < 0 || mutex >= SQLCIPHER_MUTEX_COUNT) return NULL;
- return sqlcipher_static_mutex[mutex];
-}
-
-static int sqlcipher_mem_init(void *pAppData) {
- return default_mem_methods.xInit(pAppData);
-}
-static void sqlcipher_mem_shutdown(void *pAppData) {
- default_mem_methods.xShutdown(pAppData);
-}
-static void *sqlcipher_mem_malloc(int n) {
- void *ptr = default_mem_methods.xMalloc(n);
- if(mem_security_on) {
- CODEC_TRACE_MEMORY("sqlcipher_mem_malloc: calling sqlcipher_mlock(%p,%d)\n", ptr, n);
- sqlcipher_mlock(ptr, n);
- if(!mem_security_activated) mem_security_activated = 1;
- }
- return ptr;
-}
-static int sqlcipher_mem_size(void *p) {
- return default_mem_methods.xSize(p);
-}
-static void sqlcipher_mem_free(void *p) {
- int sz;
- if(mem_security_on) {
- sz = sqlcipher_mem_size(p);
- CODEC_TRACE_MEMORY("sqlcipher_mem_free: calling sqlcipher_memset(%p,0,%d) and sqlcipher_munlock(%p, %d) \n", p, sz, p, sz);
- sqlcipher_memset(p, 0, sz);
- sqlcipher_munlock(p, sz);
- if(!mem_security_activated) mem_security_activated = 1;
- }
- default_mem_methods.xFree(p);
-}
-static void *sqlcipher_mem_realloc(void *p, int n) {
- return default_mem_methods.xRealloc(p, n);
-}
-static int sqlcipher_mem_roundup(int n) {
- return default_mem_methods.xRoundup(n);
-}
-
-static sqlcipher_sqlite3_mem_methods sqlcipher_mem_methods = {
- sqlcipher_mem_malloc,
- sqlcipher_mem_free,
- sqlcipher_mem_realloc,
- sqlcipher_mem_size,
- sqlcipher_mem_roundup,
- sqlcipher_mem_init,
- sqlcipher_mem_shutdown,
- 0
-};
-
-void sqlcipher_init_memmethods() {
- if(mem_security_initialized) return;
- if(sqlcipher_sqlite3_config(SQLITE_CONFIG_GETMALLOC, &default_mem_methods) != SQLITE_OK ||
- sqlcipher_sqlite3_config(SQLITE_CONFIG_MALLOC, &sqlcipher_mem_methods) != SQLITE_OK) {
- mem_security_on = mem_security_activated = 0;
- }
- mem_security_initialized = 1;
-}
-
-int sqlcipher_register_provider(sqlcipher_provider *p) {
- CODEC_TRACE_MUTEX("sqlcipher_register_provider: entering SQLCIPHER_MUTEX_PROVIDER\n");
- sqlcipher_sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER));
- CODEC_TRACE_MUTEX("sqlcipher_register_provider: entered SQLCIPHER_MUTEX_PROVIDER\n");
-
- if(default_provider != NULL && default_provider != p) {
- /* only free the current registerd provider if it has been initialized
- and it isn't a pointer to the same provider passed to the function
- (i.e. protect against a caller calling register twice for the same provider) */
- sqlcipher_free(default_provider, sizeof(sqlcipher_provider));
- }
- default_provider = p;
- CODEC_TRACE_MUTEX("sqlcipher_register_provider: leaving SQLCIPHER_MUTEX_PROVIDER\n");
- sqlcipher_sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER));
- CODEC_TRACE_MUTEX("sqlcipher_register_provider: left SQLCIPHER_MUTEX_PROVIDER\n");
-
- return SQLITE_OK;
-}
-
-/* return a pointer to the currently registered provider. This will
- allow an application to fetch the current registered provider and
- make minor changes to it */
-sqlcipher_provider* sqlcipher_get_provider() {
- return default_provider;
-}
-
-void sqlcipher_activate() {
- CODEC_TRACE_MUTEX("sqlcipher_activate: entering static master mutex\n");
- sqlcipher_sqlite3_mutex_enter(sqlcipher_sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER));
- CODEC_TRACE_MUTEX("sqlcipher_activate: entered static master mutex\n");
-
- /* allocate new mutexes */
- if(sqlcipher_activate_count == 0) {
- int i;
- for(i = 0; i < SQLCIPHER_MUTEX_COUNT; i++) {
- sqlcipher_static_mutex[i] = sqlcipher_sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
- }
- }
-
- /* check to see if there is a provider registered at this point
- if there no provider registered at this point, register the
- default provider */
- if(sqlcipher_get_provider() == NULL) {
- sqlcipher_provider *p = sqlcipher_malloc(sizeof(sqlcipher_provider));
-#if defined (SQLCIPHER_CRYPTO_CC)
- extern int sqlcipher_cc_setup(sqlcipher_provider *p);
- sqlcipher_cc_setup(p);
-#elif defined (SQLCIPHER_CRYPTO_LIBTOMCRYPT)
- extern int sqlcipher_ltc_setup(sqlcipher_provider *p);
- sqlcipher_ltc_setup(p);
-#elif defined (SQLCIPHER_CRYPTO_NSS)
- extern int sqlcipher_nss_setup(sqlcipher_provider *p);
- sqlcipher_nss_setup(p);
-#elif defined (SQLCIPHER_CRYPTO_OPENSSL)
- extern int sqlcipher_openssl_setup(sqlcipher_provider *p);
- sqlcipher_openssl_setup(p);
-#else
-#error "NO DEFAULT SQLCIPHER CRYPTO PROVIDER DEFINED"
+#ifdef SQLITE_DEFAULT_ROWEST
+ "DEFAULT_ROWEST=" CTIMEOPT_VAL(SQLITE_DEFAULT_ROWEST),
#endif
- CODEC_TRACE("sqlcipher_activate: calling sqlcipher_register_provider(%p)\n", p);
-#ifdef SQLCIPHER_EXT
- sqlcipher_ext_provider_setup(p);
+#ifdef SQLITE_DEFAULT_SECTOR_SIZE
+ "DEFAULT_SECTOR_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_SECTOR_SIZE),
#endif
- sqlcipher_register_provider(p);
- CODEC_TRACE("sqlcipher_activate: called sqlcipher_register_provider(%p)\n",p);
- }
-
- sqlcipher_activate_count++; /* increment activation count */
-
- CODEC_TRACE_MUTEX("sqlcipher_activate: leaving static master mutex\n");
- sqlcipher_sqlite3_mutex_leave(sqlcipher_sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER));
- CODEC_TRACE_MUTEX("sqlcipher_activate: left static master mutex\n");
-}
-
-void sqlcipher_deactivate() {
- CODEC_TRACE_MUTEX("sqlcipher_deactivate: entering static master mutex\n");
- sqlcipher_sqlite3_mutex_enter(sqlcipher_sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER));
- CODEC_TRACE_MUTEX("sqlcipher_deactivate: entered static master mutex\n");
-
- sqlcipher_activate_count--;
- /* if no connections are using sqlcipher, cleanup globals */
- if(sqlcipher_activate_count < 1) {
-
- CODEC_TRACE_MUTEX("sqlcipher_deactivate: entering SQLCIPHER_MUTEX_PROVIDER\n");
- sqlcipher_sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER));
- CODEC_TRACE_MUTEX("sqlcipher_deactivate: entered SQLCIPHER_MUTEX_PROVIDER\n");
-
- if(default_provider != NULL) {
- sqlcipher_free(default_provider, sizeof(sqlcipher_provider));
- default_provider = NULL;
- }
-
- CODEC_TRACE_MUTEX("sqlcipher_deactivate: leaving SQLCIPHER_MUTEX_PROVIDER\n");
- sqlcipher_sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER));
- CODEC_TRACE_MUTEX("sqlcipher_deactivate: left SQLCIPHER_MUTEX_PROVIDER\n");
-
-#ifdef SQLCIPHER_EXT
- sqlcipher_ext_provider_destroy();
+#ifdef SQLITE_DEFAULT_SYNCHRONOUS
+ "DEFAULT_SYNCHRONOUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_SYNCHRONOUS),
#endif
-
- /* last connection closed, free mutexes */
- if(sqlcipher_activate_count == 0) {
- int i;
- for(i = 0; i < SQLCIPHER_MUTEX_COUNT; i++) {
- sqlcipher_sqlite3_mutex_free(sqlcipher_static_mutex[i]);
- }
- }
- sqlcipher_activate_count = 0; /* reset activation count */
- }
-
- CODEC_TRACE_MUTEX("sqlcipher_deactivate: leaving static master mutex\n");
- sqlcipher_sqlite3_mutex_leave(sqlcipher_sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER));
- CODEC_TRACE_MUTEX("sqlcipher_deactivate: left static master mutex\n");
-}
-
-/* constant time memset using volitile to avoid having the memset
- optimized out by the compiler.
- Note: As suggested by Joachim Schipper (joachim.schipper@fox-it.com)
-*/
-void* sqlcipher_memset(void *v, unsigned char value, u64 len) {
- u64 i = 0;
- volatile unsigned char *a = v;
-
- if (v == NULL) return v;
-
- CODEC_TRACE_MEMORY("sqlcipher_memset: setting %p[0-%llu]=%d)\n", a, len, value);
- for(i = 0; i < len; i++) {
- a[i] = value;
- }
-
- return v;
-}
-
-/* constant time memory check tests every position of a memory segement
- matches a single value (i.e. the memory is all zeros)
- returns 0 if match, 1 of no match */
-int sqlcipher_ismemset(const void *v, unsigned char value, u64 len) {
- const unsigned char *a = v;
- u64 i = 0, result = 0;
-
- for(i = 0; i < len; i++) {
- result |= a[i] ^ value;
- }
-
- return (result != 0);
-}
-
-/* constant time memory comparison routine.
- returns 0 if match, 1 if no match */
-int sqlcipher_memcmp(const void *v0, const void *v1, int len) {
- const unsigned char *a0 = v0, *a1 = v1;
- int i = 0, result = 0;
-
- for(i = 0; i < len; i++) {
- result |= a0[i] ^ a1[i];
- }
-
- return (result != 0);
-}
-
-void sqlcipher_mlock(void *ptr, u64 sz) {
-#ifndef OMIT_MEMLOCK
-#if defined(__unix__) || defined(__APPLE__)
- int rc;
- unsigned long pagesize = sysconf(_SC_PAGESIZE);
- unsigned long offset = (unsigned long) ptr % pagesize;
-
- if(ptr == NULL || sz == 0) return;
-
- CODEC_TRACE_MEMORY("sqlcipher_mem_lock: calling mlock(%p,%lu); _SC_PAGESIZE=%lu\n", ptr - offset, sz + offset, pagesize);
- rc = mlock(ptr - offset, sz + offset);
- if(rc!=0) {
- CODEC_TRACE_MEMORY("sqlcipher_mem_lock: mlock(%p,%lu) returned %d errno=%d\n", ptr - offset, sz + offset, rc, errno);
- }
-#elif defined(_WIN32)
-#if !(defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP || WINAPI_FAMILY == WINAPI_FAMILY_APP))
- int rc;
- CODEC_TRACE("sqlcipher_mem_lock: calling VirtualLock(%p,%d)\n", ptr, sz);
- rc = VirtualLock(ptr, sz);
- if(rc==0) {
- CODEC_TRACE("sqlcipher_mem_lock: VirtualLock(%p,%d) returned %d LastError=%d\n", ptr, sz, rc, GetLastError());
- }
+#ifdef SQLITE_DEFAULT_WAL_AUTOCHECKPOINT
+ "DEFAULT_WAL_AUTOCHECKPOINT=" CTIMEOPT_VAL(SQLITE_DEFAULT_WAL_AUTOCHECKPOINT),
#endif
+#ifdef SQLITE_DEFAULT_WAL_SYNCHRONOUS
+ "DEFAULT_WAL_SYNCHRONOUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_WAL_SYNCHRONOUS),
#endif
+#ifdef SQLITE_DEFAULT_WORKER_THREADS
+ "DEFAULT_WORKER_THREADS=" CTIMEOPT_VAL(SQLITE_DEFAULT_WORKER_THREADS),
#endif
-}
-
-void sqlcipher_munlock(void *ptr, u64 sz) {
-#ifndef OMIT_MEMLOCK
-#if defined(__unix__) || defined(__APPLE__)
- int rc;
- unsigned long pagesize = sysconf(_SC_PAGESIZE);
- unsigned long offset = (unsigned long) ptr % pagesize;
-
- if(ptr == NULL || sz == 0) return;
-
- CODEC_TRACE_MEMORY("sqlcipher_mem_unlock: calling munlock(%p,%lu)\n", ptr - offset, sz + offset);
- rc = munlock(ptr - offset, sz + offset);
- if(rc!=0) {
- CODEC_TRACE_MEMORY("sqlcipher_mem_unlock: munlock(%p,%lu) returned %d errno=%d\n", ptr - offset, sz + offset, rc, errno);
- }
-#elif defined(_WIN32)
-#if !(defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP || WINAPI_FAMILY == WINAPI_FAMILY_APP))
- int rc;
- CODEC_TRACE("sqlcipher_mem_lock: calling VirtualUnlock(%p,%d)\n", ptr, sz);
- rc = VirtualUnlock(ptr, sz);
- if(!rc) {
- CODEC_TRACE("sqlcipher_mem_unlock: VirtualUnlock(%p,%d) returned %d LastError=%d\n", ptr, sz, rc, GetLastError());
- }
+#ifdef SQLITE_DIRECT_OVERFLOW_READ
+ "DIRECT_OVERFLOW_READ",
#endif
+#ifdef SQLITE_DISABLE_DIRSYNC
+ "DISABLE_DIRSYNC",
#endif
+#ifdef SQLITE_DISABLE_FTS3_UNICODE
+ "DISABLE_FTS3_UNICODE",
#endif
-}
-
-/**
- * Free and wipe memory. Uses SQLites internal sqlcipher_sqlite3_free so that memory
- * can be countend and memory leak detection works in the test suite.
- * If ptr is not null memory will be freed.
- * If sz is greater than zero, the memory will be overwritten with zero before it is freed
- * If sz is > 0, and not compiled with OMIT_MEMLOCK, system will attempt to unlock the
- * memory segment so it can be paged
- */
-void sqlcipher_free(void *ptr, u64 sz) {
- CODEC_TRACE_MEMORY("sqlcipher_free: calling sqlcipher_memset(%p,0,%llu)\n", ptr, sz);
- sqlcipher_memset(ptr, 0, sz);
- sqlcipher_munlock(ptr, sz);
- sqlcipher_sqlite3_free(ptr);
-}
-
-/**
- * allocate memory. Uses sqlite's internall malloc wrapper so memory can be
- * reference counted and leak detection works. Unless compiled with OMIT_MEMLOCK
- * attempts to lock the memory pages so sensitive information won't be swapped
- */
-void* sqlcipher_malloc(u64 sz) {
- void *ptr;
- CODEC_TRACE_MEMORY("sqlcipher_malloc: calling sqlcipher_sqlite3Malloc(%llu)\n", sz);
- ptr = sqlcipher_sqlite3Malloc(sz);
- CODEC_TRACE_MEMORY("sqlcipher_malloc: calling sqlcipher_memset(%p,0,%llu)\n", ptr, sz);
- sqlcipher_memset(ptr, 0, sz);
- sqlcipher_mlock(ptr, sz);
- return ptr;
-}
-
-char* sqlcipher_version() {
-#ifdef CIPHER_VERSION_QUALIFIER
- char *version = sqlcipher_sqlite3_mprintf("%s %s %s", CIPHER_XSTR(CIPHER_VERSION_NUMBER), CIPHER_XSTR(CIPHER_VERSION_QUALIFIER), CIPHER_XSTR(CIPHER_VERSION_BUILD));
-#else
- char *version = sqlcipher_sqlite3_mprintf("%s %s", CIPHER_XSTR(CIPHER_VERSION_NUMBER), CIPHER_XSTR(CIPHER_VERSION_BUILD));
+#ifdef SQLITE_DISABLE_FTS4_DEFERRED
+ "DISABLE_FTS4_DEFERRED",
#endif
- return version;
-}
-
-/**
- * Initialize new cipher_ctx struct. This function will allocate memory
- * for the cipher context and for the key
- *
- * returns SQLITE_OK if initialization was successful
- * returns SQLITE_NOMEM if an error occured allocating memory
- */
-static int sqlcipher_cipher_ctx_init(codec_ctx *ctx, cipher_ctx **iCtx) {
- cipher_ctx *c_ctx;
- CODEC_TRACE("sqlcipher_cipher_ctx_init: allocating context\n");
- *iCtx = (cipher_ctx *) sqlcipher_malloc(sizeof(cipher_ctx));
- c_ctx = *iCtx;
- if(c_ctx == NULL) return SQLITE_NOMEM;
-
- CODEC_TRACE("sqlcipher_cipher_ctx_init: allocating key\n");
- c_ctx->key = (unsigned char *) sqlcipher_malloc(ctx->key_sz);
-
- CODEC_TRACE("sqlcipher_cipher_ctx_init: allocating hmac_key\n");
- c_ctx->hmac_key = (unsigned char *) sqlcipher_malloc(ctx->key_sz);
-
- if(c_ctx->key == NULL) return SQLITE_NOMEM;
- if(c_ctx->hmac_key == NULL) return SQLITE_NOMEM;
-
- return SQLITE_OK;
-}
-
-/**
- * Free and wipe memory associated with a cipher_ctx
- */
-static void sqlcipher_cipher_ctx_free(codec_ctx* ctx, cipher_ctx **iCtx) {
- cipher_ctx *c_ctx = *iCtx;
- CODEC_TRACE("cipher_ctx_free: entered iCtx=%p\n", iCtx);
- sqlcipher_free(c_ctx->key, ctx->key_sz);
- sqlcipher_free(c_ctx->hmac_key, ctx->key_sz);
- sqlcipher_free(c_ctx->pass, c_ctx->pass_sz);
- sqlcipher_free(c_ctx->keyspec, ctx->keyspec_sz);
- sqlcipher_free(c_ctx, sizeof(cipher_ctx));
-}
-
-static int sqlcipher_codec_ctx_reserve_setup(codec_ctx *ctx) {
- int base_reserve = ctx->iv_sz; /* base reserve size will be IV only */
- int reserve = base_reserve;
-
- ctx->hmac_sz = ctx->provider->get_hmac_sz(ctx->provider_ctx, ctx->hmac_algorithm);
-
- if(sqlcipher_codec_ctx_get_use_hmac(ctx))
- reserve += ctx->hmac_sz; /* if reserve will include hmac, update that size */
-
- /* calculate the amount of reserve needed in even increments of the cipher block size */
- reserve = ((reserve % ctx->block_sz) == 0) ? reserve :
- ((reserve / ctx->block_sz) + 1) * ctx->block_sz;
-
- CODEC_TRACE("sqlcipher_codec_ctx_reserve_setup: base_reserve=%d block_sz=%d md_size=%d reserve=%d\n",
- base_reserve, ctx->block_sz, ctx->hmac_sz, reserve);
-
- ctx->reserve_sz = reserve;
-
- return SQLITE_OK;
-}
-
-/**
- * Compare one cipher_ctx to another.
- *
- * returns 0 if all the parameters (except the derived key data) are the same
- * returns 1 otherwise
- */
-static int sqlcipher_cipher_ctx_cmp(cipher_ctx *c1, cipher_ctx *c2) {
- int are_equal = (
- c1->pass_sz == c2->pass_sz
- && (
- c1->pass == c2->pass
- || !sqlcipher_memcmp((const unsigned char*)c1->pass,
- (const unsigned char*)c2->pass,
- c1->pass_sz)
- ));
-
- CODEC_TRACE("sqlcipher_cipher_ctx_cmp: entered \
- c1=%p c2=%p \
- c1->pass_sz=%d c2->pass_sz=%d \
- c1->pass=%p c2->pass=%p \
- c1->pass=%s c2->pass=%s \
- sqlcipher_memcmp=%d \
- are_equal=%d \
- \n",
- c1, c2,
- c1->pass_sz, c2->pass_sz,
- c1->pass, c2->pass,
- c1->pass, c2->pass,
- (c1->pass == NULL || c2->pass == NULL)
- ? -1 : sqlcipher_memcmp(
- (const unsigned char*)c1->pass,
- (const unsigned char*)c2->pass,
- c1->pass_sz),
- are_equal
- );
-
- return !are_equal; /* return 0 if they are the same, 1 otherwise */
-}
-
-/**
- * Copy one cipher_ctx to another. For instance, assuming that read_ctx is a
- * fully initialized context, you could copy it to write_ctx and all yet data
- * and pass information across
- *
- * returns SQLITE_OK if initialization was successful
- * returns SQLITE_NOMEM if an error occured allocating memory
- */
-static int sqlcipher_cipher_ctx_copy(codec_ctx *ctx, cipher_ctx *target, cipher_ctx *source) {
- void *key = target->key;
- void *hmac_key = target->hmac_key;
-
- CODEC_TRACE("sqlcipher_cipher_ctx_copy: entered target=%p, source=%p\n", target, source);
- sqlcipher_free(target->pass, target->pass_sz);
- sqlcipher_free(target->keyspec, ctx->keyspec_sz);
- memcpy(target, source, sizeof(cipher_ctx));
-
- target->key = key; /* restore pointer to previously allocated key data */
- memcpy(target->key, source->key, ctx->key_sz);
-
- target->hmac_key = hmac_key; /* restore pointer to previously allocated hmac key data */
- memcpy(target->hmac_key, source->hmac_key, ctx->key_sz);
-
- if(source->pass && source->pass_sz) {
- target->pass = sqlcipher_malloc(source->pass_sz);
- if(target->pass == NULL) return SQLITE_NOMEM;
- memcpy(target->pass, source->pass, source->pass_sz);
- }
- if(source->keyspec) {
- target->keyspec = sqlcipher_malloc(ctx->keyspec_sz);
- if(target->keyspec == NULL) return SQLITE_NOMEM;
- memcpy(target->keyspec, source->keyspec, ctx->keyspec_sz);
- }
- return SQLITE_OK;
-}
-
-/**
- * Set the keyspec for the cipher_ctx
- *
- * returns SQLITE_OK if assignment was successfull
- * returns SQLITE_NOMEM if an error occured allocating memory
- */
-static int sqlcipher_cipher_ctx_set_keyspec(codec_ctx *ctx, cipher_ctx *c_ctx, const unsigned char *key) {
- /* free, zero existing pointers and size */
- sqlcipher_free(c_ctx->keyspec, ctx->keyspec_sz);
- c_ctx->keyspec = NULL;
-
- c_ctx->keyspec = sqlcipher_malloc(ctx->keyspec_sz);
- if(c_ctx->keyspec == NULL) return SQLITE_NOMEM;
-
- c_ctx->keyspec[0] = 'x';
- c_ctx->keyspec[1] = '\'';
- cipher_bin2hex(key, ctx->key_sz, c_ctx->keyspec + 2);
- cipher_bin2hex(ctx->kdf_salt, ctx->kdf_salt_sz, c_ctx->keyspec + (ctx->key_sz * 2) + 2);
- c_ctx->keyspec[ctx->keyspec_sz - 1] = '\'';
- return SQLITE_OK;
-}
-
-int sqlcipher_codec_get_store_pass(codec_ctx *ctx) {
- return ctx->store_pass;
-}
-
-void sqlcipher_codec_set_store_pass(codec_ctx *ctx, int value) {
- ctx->store_pass = value;
-}
-
-void sqlcipher_codec_get_pass(codec_ctx *ctx, void **zKey, int *nKey) {
- *zKey = ctx->read_ctx->pass;
- *nKey = ctx->read_ctx->pass_sz;
-}
-
-static void sqlcipher_set_derive_key(codec_ctx *ctx, int derive) {
- if(ctx->read_ctx != NULL) ctx->read_ctx->derive_key = 1;
- if(ctx->write_ctx != NULL) ctx->write_ctx->derive_key = 1;
-}
-
-/**
- * Set the passphrase for the cipher_ctx
- *
- * returns SQLITE_OK if assignment was successfull
- * returns SQLITE_NOMEM if an error occured allocating memory
- */
-static int sqlcipher_cipher_ctx_set_pass(cipher_ctx *ctx, const void *zKey, int nKey) {
- /* free, zero existing pointers and size */
- sqlcipher_free(ctx->pass, ctx->pass_sz);
- ctx->pass = NULL;
- ctx->pass_sz = 0;
-
- if(zKey && nKey) { /* if new password is provided, copy it */
- ctx->pass_sz = nKey;
- ctx->pass = sqlcipher_malloc(nKey);
- if(ctx->pass == NULL) return SQLITE_NOMEM;
- memcpy(ctx->pass, zKey, nKey);
- }
- return SQLITE_OK;
-}
-
-int sqlcipher_codec_ctx_set_pass(codec_ctx *ctx, const void *zKey, int nKey, int for_ctx) {
- cipher_ctx *c_ctx = for_ctx ? ctx->write_ctx : ctx->read_ctx;
- int rc;
-
- if((rc = sqlcipher_cipher_ctx_set_pass(c_ctx, zKey, nKey)) != SQLITE_OK) return rc;
- c_ctx->derive_key = 1;
-
- if(for_ctx == 2)
- if((rc = sqlcipher_cipher_ctx_copy(ctx, for_ctx ? ctx->read_ctx : ctx->write_ctx, c_ctx)) != SQLITE_OK)
- return rc;
-
- return SQLITE_OK;
-}
-
-const char* sqlcipher_codec_ctx_get_cipher(codec_ctx *ctx) {
- return ctx->provider->get_cipher(ctx->provider_ctx);
-}
-
-/* set the global default KDF iteration */
-void sqlcipher_set_default_kdf_iter(int iter) {
- default_kdf_iter = iter;
-}
-
-int sqlcipher_get_default_kdf_iter() {
- return default_kdf_iter;
-}
-
-int sqlcipher_codec_ctx_set_kdf_iter(codec_ctx *ctx, int kdf_iter) {
- ctx->kdf_iter = kdf_iter;
- sqlcipher_set_derive_key(ctx, 1);
- return SQLITE_OK;
-}
-
-int sqlcipher_codec_ctx_get_kdf_iter(codec_ctx *ctx) {
- return ctx->kdf_iter;
-}
-
-int sqlcipher_codec_ctx_set_fast_kdf_iter(codec_ctx *ctx, int fast_kdf_iter) {
- ctx->fast_kdf_iter = fast_kdf_iter;
- sqlcipher_set_derive_key(ctx, 1);
- return SQLITE_OK;
-}
-
-int sqlcipher_codec_ctx_get_fast_kdf_iter(codec_ctx *ctx) {
- return ctx->fast_kdf_iter;
-}
-
-/* set the global default flag for HMAC */
-void sqlcipher_set_default_use_hmac(int use) {
- if(use) default_flags |= CIPHER_FLAG_HMAC;
- else default_flags &= ~CIPHER_FLAG_HMAC;
-}
-
-int sqlcipher_get_default_use_hmac() {
- return (default_flags & CIPHER_FLAG_HMAC) != 0;
-}
-
-void sqlcipher_set_hmac_salt_mask(unsigned char mask) {
- hmac_salt_mask = mask;
-}
-
-unsigned char sqlcipher_get_hmac_salt_mask() {
- return hmac_salt_mask;
-}
-
-/* set the codec flag for whether this individual database should be using hmac */
-int sqlcipher_codec_ctx_set_use_hmac(codec_ctx *ctx, int use) {
- if(use) {
- sqlcipher_codec_ctx_set_flag(ctx, CIPHER_FLAG_HMAC);
- } else {
- sqlcipher_codec_ctx_unset_flag(ctx, CIPHER_FLAG_HMAC);
- }
-
- return sqlcipher_codec_ctx_reserve_setup(ctx);
-}
-
-int sqlcipher_codec_ctx_get_use_hmac(codec_ctx *ctx) {
- return (ctx->flags & CIPHER_FLAG_HMAC) != 0;
-}
-
-/* the length of plaintext header size must be:
- * 1. greater than or equal to zero
- * 2. a multiple of the cipher block size
- * 3. less than the usable size of the first database page
- */
-int sqlcipher_set_default_plaintext_header_size(int size) {
- default_plaintext_header_sz = size;
- return SQLITE_OK;
-}
-
-int sqlcipher_codec_ctx_set_plaintext_header_size(codec_ctx *ctx, int size) {
- if(size >= 0 && (size % ctx->block_sz) == 0 && size < (ctx->page_sz - ctx->reserve_sz)) {
- ctx->plaintext_header_sz = size;
- return SQLITE_OK;
- }
- ctx->plaintext_header_sz = -1;
- return SQLITE_ERROR;
-}
-
-int sqlcipher_get_default_plaintext_header_size() {
- return default_plaintext_header_sz;
-}
-
-int sqlcipher_codec_ctx_get_plaintext_header_size(codec_ctx *ctx) {
- return ctx->plaintext_header_sz;
-}
-
-/* manipulate HMAC algorithm */
-int sqlcipher_set_default_hmac_algorithm(int algorithm) {
- default_hmac_algorithm = algorithm;
- return SQLITE_OK;
-}
-
-int sqlcipher_codec_ctx_set_hmac_algorithm(codec_ctx *ctx, int algorithm) {
- ctx->hmac_algorithm = algorithm;
- return sqlcipher_codec_ctx_reserve_setup(ctx);
-}
-
-int sqlcipher_get_default_hmac_algorithm() {
- return default_hmac_algorithm;
-}
-
-int sqlcipher_codec_ctx_get_hmac_algorithm(codec_ctx *ctx) {
- return ctx->hmac_algorithm;
-}
-
-/* manipulate KDF algorithm */
-int sqlcipher_set_default_kdf_algorithm(int algorithm) {
- default_kdf_algorithm = algorithm;
- return SQLITE_OK;
-}
-
-int sqlcipher_codec_ctx_set_kdf_algorithm(codec_ctx *ctx, int algorithm) {
- ctx->kdf_algorithm = algorithm;
- return SQLITE_OK;
-}
-
-int sqlcipher_get_default_kdf_algorithm() {
- return default_kdf_algorithm;
-}
-
-int sqlcipher_codec_ctx_get_kdf_algorithm(codec_ctx *ctx) {
- return ctx->kdf_algorithm;
-}
-
-int sqlcipher_codec_ctx_set_flag(codec_ctx *ctx, unsigned int flag) {
- ctx->flags |= flag;
- return SQLITE_OK;
-}
-
-int sqlcipher_codec_ctx_unset_flag(codec_ctx *ctx, unsigned int flag) {
- ctx->flags &= ~flag;
- return SQLITE_OK;
-}
-
-int sqlcipher_codec_ctx_get_flag(codec_ctx *ctx, unsigned int flag) {
- return (ctx->flags & flag) != 0;
-}
-
-void sqlcipher_codec_ctx_set_error(codec_ctx *ctx, int error) {
- CODEC_TRACE("sqlcipher_codec_ctx_set_error: ctx=%p, error=%d\n", ctx, error);
- sqlcipher_sqlite3pager_error(ctx->pBt->pBt->pPager, error);
- ctx->pBt->pBt->db->errCode = error;
-}
-
-int sqlcipher_codec_ctx_get_reservesize(codec_ctx *ctx) {
- return ctx->reserve_sz;
-}
-
-void* sqlcipher_codec_ctx_get_data(codec_ctx *ctx) {
- return ctx->buffer;
-}
-
-static int sqlcipher_codec_ctx_init_kdf_salt(codec_ctx *ctx) {
- sqlcipher_sqlite3_file *fd = sqlcipher_sqlite3PagerFile(ctx->pBt->pBt->pPager);
-
- if(!ctx->need_kdf_salt) {
- return SQLITE_OK; /* don't reload salt when not needed */
- }
-
- /* read salt from header, if present, otherwise generate a new random salt */
- CODEC_TRACE("sqlcipher_codec_ctx_init_kdf_salt: obtaining salt\n");
- if(fd == NULL || fd->pMethods == 0 || sqlcipher_sqlite3OsRead(fd, ctx->kdf_salt, ctx->kdf_salt_sz, 0) != SQLITE_OK) {
- CODEC_TRACE("sqlcipher_codec_ctx_init_kdf_salt: unable to read salt from file header, generating random\n");
- if(ctx->provider->random(ctx->provider_ctx, ctx->kdf_salt, ctx->kdf_salt_sz) != SQLITE_OK) return SQLITE_ERROR;
- }
- ctx->need_kdf_salt = 0;
- return SQLITE_OK;
-}
-
-int sqlcipher_codec_ctx_set_kdf_salt(codec_ctx *ctx, unsigned char *salt, int size) {
- if(size >= ctx->kdf_salt_sz) {
- memcpy(ctx->kdf_salt, salt, ctx->kdf_salt_sz);
- ctx->need_kdf_salt = 0;
- return SQLITE_OK;
- }
- return SQLITE_ERROR;
-}
-
-int sqlcipher_codec_ctx_get_kdf_salt(codec_ctx *ctx, void** salt) {
- int rc = SQLITE_OK;
- if(ctx->need_kdf_salt) {
- rc = sqlcipher_codec_ctx_init_kdf_salt(ctx);
- }
- *salt = ctx->kdf_salt;
- return rc;
-}
-
-void sqlcipher_codec_get_keyspec(codec_ctx *ctx, void **zKey, int *nKey) {
- *zKey = ctx->read_ctx->keyspec;
- *nKey = ctx->keyspec_sz;
-}
-
-int sqlcipher_codec_ctx_set_pagesize(codec_ctx *ctx, int size) {
- if(!((size != 0) && ((size & (size - 1)) == 0)) || size < 512 || size > 65536) {
- CODEC_TRACE(("cipher_page_size not a power of 2 and between 512 and 65536 inclusive\n"));
- return SQLITE_ERROR;
- }
- /* attempt to free the existing page buffer */
- sqlcipher_free(ctx->buffer,ctx->page_sz);
- ctx->page_sz = size;
-
- /* pre-allocate a page buffer of PageSize bytes. This will
- be used as a persistent buffer for encryption and decryption
- operations to avoid overhead of multiple memory allocations*/
- ctx->buffer = sqlcipher_malloc(size);
- if(ctx->buffer == NULL) return SQLITE_NOMEM;
-
- return SQLITE_OK;
-}
-
-int sqlcipher_codec_ctx_get_pagesize(codec_ctx *ctx) {
- return ctx->page_sz;
-}
-
-void sqlcipher_set_default_pagesize(int page_size) {
- default_page_size = page_size;
-}
-
-int sqlcipher_get_default_pagesize() {
- return default_page_size;
-}
-
-void sqlcipher_set_mem_security(int on) {
- mem_security_on = on;
- mem_security_activated = 0;
-}
-
-int sqlcipher_get_mem_security() {
- return mem_security_on && mem_security_activated;
-}
-
-
-int sqlcipher_codec_ctx_init(codec_ctx **iCtx, Db *pDb, Pager *pPager, const void *zKey, int nKey) {
- int rc;
- codec_ctx *ctx;
-
- CODEC_TRACE("sqlcipher_codec_ctx_init: allocating context\n");
-
- *iCtx = sqlcipher_malloc(sizeof(codec_ctx));
- ctx = *iCtx;
-
- if(ctx == NULL) return SQLITE_NOMEM;
-
- ctx->pBt = pDb->pBt; /* assign pointer to database btree structure */
-
- /* allocate space for salt data. Then read the first 16 bytes
- directly off the database file. This is the salt for the
- key derivation function. If we get a short read allocate
- a new random salt value */
- CODEC_TRACE("sqlcipher_codec_ctx_init: allocating kdf_salt\n");
- ctx->kdf_salt_sz = FILE_HEADER_SZ;
- ctx->kdf_salt = sqlcipher_malloc(ctx->kdf_salt_sz);
- if(ctx->kdf_salt == NULL) return SQLITE_NOMEM;
-
- /* allocate space for separate hmac salt data. We want the
- HMAC derivation salt to be different than the encryption
- key derivation salt */
- CODEC_TRACE("sqlcipher_codec_ctx_init: allocating hmac_kdf_salt\n");
- ctx->hmac_kdf_salt = sqlcipher_malloc(ctx->kdf_salt_sz);
- if(ctx->hmac_kdf_salt == NULL) return SQLITE_NOMEM;
-
- /* setup default flags */
- ctx->flags = default_flags;
-
- /* defer attempt to read KDF salt until first use */
- ctx->need_kdf_salt = 1;
-
- /* setup the crypto provider */
- CODEC_TRACE("sqlcipher_codec_ctx_init: allocating provider\n");
- ctx->provider = (sqlcipher_provider *) sqlcipher_malloc(sizeof(sqlcipher_provider));
- if(ctx->provider == NULL) return SQLITE_NOMEM;
-
- /* make a copy of the provider to be used for the duration of the context */
- CODEC_TRACE_MUTEX("sqlcipher_codec_ctx_init: entering SQLCIPHER_MUTEX_PROVIDER\n");
- sqlcipher_sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER));
- CODEC_TRACE_MUTEX("sqlcipher_codec_ctx_init: entered SQLCIPHER_MUTEX_PROVIDER\n");
-
- memcpy(ctx->provider, default_provider, sizeof(sqlcipher_provider));
-
- CODEC_TRACE_MUTEX("sqlcipher_codec_ctx_init: leaving SQLCIPHER_MUTEX_PROVIDER\n");
- sqlcipher_sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER));
- CODEC_TRACE_MUTEX("sqlcipher_codec_ctx_init: left SQLCIPHER_MUTEX_PROVIDER\n");
-
- CODEC_TRACE("sqlcipher_codec_ctx_init: calling provider ctx_init\n");
- if((rc = ctx->provider->ctx_init(&ctx->provider_ctx)) != SQLITE_OK) return rc;
-
- ctx->key_sz = ctx->provider->get_key_sz(ctx->provider_ctx);
- ctx->iv_sz = ctx->provider->get_iv_sz(ctx->provider_ctx);
- ctx->block_sz = ctx->provider->get_block_sz(ctx->provider_ctx);
-
- /* establic the size for a hex-formated key specification, containing the
- raw encryption key and the salt used to generate it format. will be x'hexkey...hexsalt'
- so oversize by 3 bytes */
- ctx->keyspec_sz = ((ctx->key_sz + ctx->kdf_salt_sz) * 2) + 3;
-
- /*
- Always overwrite page size and set to the default because the first page of the database
- in encrypted and thus sqlite can't effectively determine the pagesize. this causes an issue in
- cases where bytes 16 & 17 of the page header are a power of 2 as reported by John Lehman
- */
- CODEC_TRACE("sqlcipher_codec_ctx_init: calling sqlcipher_codec_ctx_set_pagesize with %d\n", default_page_size);
- if((rc = sqlcipher_codec_ctx_set_pagesize(ctx, default_page_size)) != SQLITE_OK) return rc;
-
- /* establish settings for the KDF iterations and fast (HMAC) KDF iterations */
- CODEC_TRACE("sqlcipher_codec_ctx_init: setting default_kdf_iter\n");
- if((rc = sqlcipher_codec_ctx_set_kdf_iter(ctx, default_kdf_iter)) != SQLITE_OK) return rc;
-
- CODEC_TRACE("sqlcipher_codec_ctx_init: setting fast_kdf_iter\n");
- if((rc = sqlcipher_codec_ctx_set_fast_kdf_iter(ctx, FAST_PBKDF2_ITER)) != SQLITE_OK) return rc;
-
- /* set the default HMAC and KDF algorithms which will determine the reserve size */
- CODEC_TRACE("sqlcipher_codec_ctx_init: calling sqlcipher_codec_ctx_set_hmac_algorithm with %d\n", default_hmac_algorithm);
- if((rc = sqlcipher_codec_ctx_set_hmac_algorithm(ctx, default_hmac_algorithm)) != SQLITE_OK) return rc;
-
- /* Note that use_hmac is a special case that requires recalculation of page size
- so we call set_use_hmac to perform setup */
- CODEC_TRACE("sqlcipher_codec_ctx_init: setting use_hmac\n");
- if((rc = sqlcipher_codec_ctx_set_use_hmac(ctx, default_flags & CIPHER_FLAG_HMAC)) != SQLITE_OK) return rc;
-
- CODEC_TRACE("sqlcipher_codec_ctx_init: calling sqlcipher_codec_ctx_set_kdf_algorithm with %d\n", default_kdf_algorithm);
- if((rc = sqlcipher_codec_ctx_set_kdf_algorithm(ctx, default_kdf_algorithm)) != SQLITE_OK) return rc;
-
- /* setup the default plaintext header size */
- CODEC_TRACE("sqlcipher_codec_ctx_init: calling sqlcipher_codec_ctx_set_plaintext_header_size with %d\n", default_plaintext_header_sz);
- if((rc = sqlcipher_codec_ctx_set_plaintext_header_size(ctx, default_plaintext_header_sz)) != SQLITE_OK) return rc;
-
- /* initialize the read and write sub-contexts. this must happen after key_sz is established */
- CODEC_TRACE("sqlcipher_codec_ctx_init: initializing read_ctx\n");
- if((rc = sqlcipher_cipher_ctx_init(ctx, &ctx->read_ctx)) != SQLITE_OK) return rc;
-
- CODEC_TRACE("sqlcipher_codec_ctx_init: initializing write_ctx\n");
- if((rc = sqlcipher_cipher_ctx_init(ctx, &ctx->write_ctx)) != SQLITE_OK) return rc;
-
- /* set the key material on one of the sub cipher contexts and sync them up */
- CODEC_TRACE("sqlcipher_codec_ctx_init: setting pass key\n");
- if((rc = sqlcipher_codec_ctx_set_pass(ctx, zKey, nKey, 0)) != SQLITE_OK) return rc;
-
- CODEC_TRACE("sqlcipher_codec_ctx_init: copying write_ctx to read_ctx\n");
- if((rc = sqlcipher_cipher_ctx_copy(ctx, ctx->write_ctx, ctx->read_ctx)) != SQLITE_OK) return rc;
-
- return SQLITE_OK;
-}
-
-/**
- * Free and wipe memory associated with a cipher_ctx, including the allocated
- * read_ctx and write_ctx.
- */
-void sqlcipher_codec_ctx_free(codec_ctx **iCtx) {
- codec_ctx *ctx = *iCtx;
- CODEC_TRACE("codec_ctx_free: entered iCtx=%p\n", iCtx);
- sqlcipher_free(ctx->kdf_salt, ctx->kdf_salt_sz);
- sqlcipher_free(ctx->hmac_kdf_salt, ctx->kdf_salt_sz);
- sqlcipher_free(ctx->buffer, 0);
-
- ctx->provider->ctx_free(&ctx->provider_ctx);
- sqlcipher_free(ctx->provider, sizeof(sqlcipher_provider));
-
- sqlcipher_cipher_ctx_free(ctx, &ctx->read_ctx);
- sqlcipher_cipher_ctx_free(ctx, &ctx->write_ctx);
- sqlcipher_free(ctx, sizeof(codec_ctx));
-}
-
-/** convert a 32bit unsigned integer to little endian byte ordering */
-static void sqlcipher_put4byte_le(unsigned char *p, u32 v) {
- p[0] = (u8)v;
- p[1] = (u8)(v>>8);
- p[2] = (u8)(v>>16);
- p[3] = (u8)(v>>24);
-}
-
-static int sqlcipher_page_hmac(codec_ctx *ctx, cipher_ctx *c_ctx, Pgno pgno, unsigned char *in, int in_sz, unsigned char *out) {
- unsigned char pgno_raw[sizeof(pgno)];
- /* we may convert page number to consistent representation before calculating MAC for
- compatibility across big-endian and little-endian platforms.
-
- Note: The public release of sqlcipher 2.0.0 to 2.0.6 had a bug where the bytes of pgno
- were used directly in the MAC. SQLCipher convert's to little endian by default to preserve
- backwards compatibility on the most popular platforms, but can optionally be configured
- to use either big endian or native byte ordering via pragma. */
-
- if(ctx->flags & CIPHER_FLAG_LE_PGNO) { /* compute hmac using little endian pgno*/
- sqlcipher_put4byte_le(pgno_raw, pgno);
- } else if(ctx->flags & CIPHER_FLAG_BE_PGNO) { /* compute hmac using big endian pgno */
- sqlcipher_sqlite3Put4byte(pgno_raw, pgno); /* sqlcipher_sqlite3Put4byte converts 32bit uint to big endian */
- } else { /* use native byte ordering */
- memcpy(pgno_raw, &pgno, sizeof(pgno));
- }
-
- /* include the encrypted page data, initialization vector, and page number in HMAC. This will
- prevent both tampering with the ciphertext, manipulation of the IV, or resequencing otherwise
- valid pages out of order in a database */
- return ctx->provider->hmac(
- ctx->provider_ctx, ctx->hmac_algorithm, c_ctx->hmac_key,
- ctx->key_sz, in,
- in_sz, (unsigned char*) &pgno_raw,
- sizeof(pgno), out);
-}
-
-/*
- * ctx - codec context
- * pgno - page number in database
- * size - size in bytes of input and output buffers
- * mode - 1 to encrypt, 0 to decrypt
- * in - pointer to input bytes
- * out - pouter to output bytes
- */
-int sqlcipher_page_cipher(codec_ctx *ctx, int for_ctx, Pgno pgno, int mode, int page_sz, unsigned char *in, unsigned char *out) {
- cipher_ctx *c_ctx = for_ctx ? ctx->write_ctx : ctx->read_ctx;
- unsigned char *iv_in, *iv_out, *hmac_in, *hmac_out, *out_start;
- int size;
-
- /* calculate some required positions into various buffers */
- size = page_sz - ctx->reserve_sz; /* adjust size to useable size and memset reserve at end of page */
- iv_out = out + size;
- iv_in = in + size;
-
- /* hmac will be written immediately after the initialization vector. the remainder of the page reserve will contain
- random bytes. note, these pointers are only valid when using hmac */
- hmac_in = in + size + ctx->iv_sz;
- hmac_out = out + size + ctx->iv_sz;
- out_start = out; /* note the original position of the output buffer pointer, as out will be rewritten during encryption */
-
- CODEC_TRACE("codec_cipher:entered pgno=%d, mode=%d, size=%d\n", pgno, mode, size);
- CODEC_HEXDUMP("codec_cipher: input page data", in, page_sz);
-
- /* the key size should never be zero. If it is, error out. */
- if(ctx->key_sz == 0) {
- CODEC_TRACE("codec_cipher: error possible context corruption, key_sz is zero for pgno=%d\n", pgno);
- goto error;
- }
-
- if(mode == CIPHER_ENCRYPT) {
- /* start at front of the reserve block, write random data to the end */
- if(ctx->provider->random(ctx->provider_ctx, iv_out, ctx->reserve_sz) != SQLITE_OK) goto error;
- } else { /* CIPHER_DECRYPT */
- memcpy(iv_out, iv_in, ctx->iv_sz); /* copy the iv from the input to output buffer */
- }
-
- if((ctx->flags & CIPHER_FLAG_HMAC) && (mode == CIPHER_DECRYPT) && !ctx->skip_read_hmac) {
- if(sqlcipher_page_hmac(ctx, c_ctx, pgno, in, size + ctx->iv_sz, hmac_out) != SQLITE_OK) {
- CODEC_TRACE("codec_cipher: hmac operation on decrypt failed for pgno=%d\n", pgno);
- goto error;
- }
-
- CODEC_TRACE("codec_cipher: comparing hmac on in=%p out=%p hmac_sz=%d\n", hmac_in, hmac_out, ctx->hmac_sz);
- if(sqlcipher_memcmp(hmac_in, hmac_out, ctx->hmac_sz) != 0) { /* the hmac check failed */
- if(sqlcipher_ismemset(in, 0, page_sz) == 0) {
- /* first check if the entire contents of the page is zeros. If so, this page
- resulted from a short read (i.e. sqlite attempted to pull a page after the end of the file. these
- short read failures must be ignored for autovaccum mode to work so wipe the output buffer
- and return SQLITE_OK to skip the decryption step. */
- CODEC_TRACE("codec_cipher: zeroed page (short read) for pgno %d, encryption but returning SQLITE_OK\n", pgno);
- sqlcipher_memset(out, 0, page_sz);
- return SQLITE_OK;
- } else {
- /* if the page memory is not all zeros, it means the there was data and a hmac on the page.
- since the check failed, the page was either tampered with or corrupted. wipe the output buffer,
- and return SQLITE_ERROR to the caller */
- CODEC_TRACE("codec_cipher: hmac check failed for pgno=%d returning SQLITE_ERROR\n", pgno);
- goto error;
- }
- }
- }
-
- if(ctx->provider->cipher(ctx->provider_ctx, mode, c_ctx->key, ctx->key_sz, iv_out, in, size, out) != SQLITE_OK) {
- CODEC_TRACE("codec_cipher: cipher operation mode=%d failed for pgno=%d returning SQLITE_ERROR\n", mode, pgno);
- goto error;
- };
-
- if((ctx->flags & CIPHER_FLAG_HMAC) && (mode == CIPHER_ENCRYPT)) {
- if(sqlcipher_page_hmac(ctx, c_ctx, pgno, out_start, size + ctx->iv_sz, hmac_out) != SQLITE_OK) {
- CODEC_TRACE("codec_cipher: hmac operation on encrypt failed for pgno=%d\n", pgno);
- goto error;
- };
- }
-
- CODEC_HEXDUMP("codec_cipher: output page data", out_start, page_sz);
-
- return SQLITE_OK;
-error:
- sqlcipher_memset(out, 0, page_sz);
- return SQLITE_ERROR;
-}
-
-/**
- * Derive an encryption key for a cipher contex key based on the raw password.
- *
- * If the raw key data is formated as x'hex' and there are exactly enough hex chars to fill
- * the key (i.e 64 hex chars for a 256 bit key) then the key data will be used directly.
-
- * Else, if the raw key data is formated as x'hex' and there are exactly enough hex chars to fill
- * the key and the salt (i.e 92 hex chars for a 256 bit key and 16 byte salt) then it will be unpacked
- * as the key followed by the salt.
- *
- * Otherwise, a key data will be derived using PBKDF2
- *
- * returns SQLITE_OK if initialization was successful
- * returns SQLITE_ERROR if the key could't be derived (for instance if pass is NULL or pass_sz is 0)
- */
-static int sqlcipher_cipher_ctx_key_derive(codec_ctx *ctx, cipher_ctx *c_ctx) {
- int rc;
- CODEC_TRACE("cipher_ctx_key_derive: entered c_ctx->pass=%s, c_ctx->pass_sz=%d \
- ctx->kdf_salt=%p ctx->kdf_salt_sz=%d ctx->kdf_iter=%d \
- ctx->hmac_kdf_salt=%p, ctx->fast_kdf_iter=%d ctx->key_sz=%d\n",
- c_ctx->pass, c_ctx->pass_sz, ctx->kdf_salt, ctx->kdf_salt_sz, ctx->kdf_iter,
- ctx->hmac_kdf_salt, ctx->fast_kdf_iter, ctx->key_sz);
-
-
- if(c_ctx->pass && c_ctx->pass_sz) { /* if key material is present on the context for derivation */
-
- /* if necessary, initialize the salt from the header or random source */
- if(ctx->need_kdf_salt) {
- if((rc = sqlcipher_codec_ctx_init_kdf_salt(ctx)) != SQLITE_OK) return rc;
- }
-
- if (c_ctx->pass_sz == ((ctx->key_sz * 2) + 3) && sqlcipher_sqlite3StrNICmp((const char *)c_ctx->pass ,"x'", 2) == 0 && cipher_isHex(c_ctx->pass + 2, ctx->key_sz * 2)) {
- int n = c_ctx->pass_sz - 3; /* adjust for leading x' and tailing ' */
- const unsigned char *z = c_ctx->pass + 2; /* adjust lead offset of x' */
- CODEC_TRACE("cipher_ctx_key_derive: using raw key from hex\n");
- cipher_hex2bin(z, n, c_ctx->key);
- } else if (c_ctx->pass_sz == (((ctx->key_sz + ctx->kdf_salt_sz) * 2) + 3) && sqlcipher_sqlite3StrNICmp((const char *)c_ctx->pass ,"x'", 2) == 0 && cipher_isHex(c_ctx->pass + 2, (ctx->key_sz + ctx->kdf_salt_sz) * 2)) {
- const unsigned char *z = c_ctx->pass + 2; /* adjust lead offset of x' */
- CODEC_TRACE("cipher_ctx_key_derive: using raw key from hex\n");
- cipher_hex2bin(z, (ctx->key_sz * 2), c_ctx->key);
- cipher_hex2bin(z + (ctx->key_sz * 2), (ctx->kdf_salt_sz * 2), ctx->kdf_salt);
- } else {
- CODEC_TRACE("cipher_ctx_key_derive: deriving key using full PBKDF2 with %d iterations\n", ctx->kdf_iter);
- if(ctx->provider->kdf(ctx->provider_ctx, ctx->kdf_algorithm, c_ctx->pass, c_ctx->pass_sz,
- ctx->kdf_salt, ctx->kdf_salt_sz, ctx->kdf_iter,
- ctx->key_sz, c_ctx->key) != SQLITE_OK) return SQLITE_ERROR;
- }
-
- /* set the context "keyspec" containing the hex-formatted key and salt to be used when attaching databases */
- if((rc = sqlcipher_cipher_ctx_set_keyspec(ctx, c_ctx, c_ctx->key)) != SQLITE_OK) return rc;
-
- /* if this context is setup to use hmac checks, generate a seperate and different
- key for HMAC. In this case, we use the output of the previous KDF as the input to
- this KDF run. This ensures a distinct but predictable HMAC key. */
- if(ctx->flags & CIPHER_FLAG_HMAC) {
- int i;
-
- /* start by copying the kdf key into the hmac salt slot
- then XOR it with the fixed hmac salt defined at compile time
- this ensures that the salt passed in to derive the hmac key, while
- easy to derive and publically known, is not the same as the salt used
- to generate the encryption key */
- memcpy(ctx->hmac_kdf_salt, ctx->kdf_salt, ctx->kdf_salt_sz);
- for(i = 0; i < ctx->kdf_salt_sz; i++) {
- ctx->hmac_kdf_salt[i] ^= hmac_salt_mask;
- }
-
- CODEC_TRACE("cipher_ctx_key_derive: deriving hmac key from encryption key using PBKDF2 with %d iterations\n",
- ctx->fast_kdf_iter);
-
-
- if(ctx->provider->kdf(ctx->provider_ctx, ctx->kdf_algorithm, c_ctx->key, ctx->key_sz,
- ctx->hmac_kdf_salt, ctx->kdf_salt_sz, ctx->fast_kdf_iter,
- ctx->key_sz, c_ctx->hmac_key) != SQLITE_OK) return SQLITE_ERROR;
- }
-
- c_ctx->derive_key = 0;
- return SQLITE_OK;
- };
- return SQLITE_ERROR;
-}
-
-int sqlcipher_codec_key_derive(codec_ctx *ctx) {
- /* derive key on first use if necessary */
- if(ctx->read_ctx->derive_key) {
- if(sqlcipher_cipher_ctx_key_derive(ctx, ctx->read_ctx) != SQLITE_OK) return SQLITE_ERROR;
- }
-
- if(ctx->write_ctx->derive_key) {
- if(sqlcipher_cipher_ctx_cmp(ctx->write_ctx, ctx->read_ctx) == 0) {
- /* the relevant parameters are the same, just copy read key */
- if(sqlcipher_cipher_ctx_copy(ctx, ctx->write_ctx, ctx->read_ctx) != SQLITE_OK) return SQLITE_ERROR;
- } else {
- if(sqlcipher_cipher_ctx_key_derive(ctx, ctx->write_ctx) != SQLITE_OK) return SQLITE_ERROR;
- }
- }
-
- /* TODO: wipe and free passphrase after key derivation */
- if(ctx->store_pass != 1) {
- sqlcipher_cipher_ctx_set_pass(ctx->read_ctx, NULL, 0);
- sqlcipher_cipher_ctx_set_pass(ctx->write_ctx, NULL, 0);
- }
-
- return SQLITE_OK;
-}
-
-int sqlcipher_codec_key_copy(codec_ctx *ctx, int source) {
- if(source == CIPHER_READ_CTX) {
- return sqlcipher_cipher_ctx_copy(ctx, ctx->write_ctx, ctx->read_ctx);
- } else {
- return sqlcipher_cipher_ctx_copy(ctx, ctx->read_ctx, ctx->write_ctx);
- }
-}
-
-const char* sqlcipher_codec_get_cipher_provider(codec_ctx *ctx) {
- return ctx->provider->get_provider_name(ctx->provider_ctx);
-}
-
-
-static int sqlcipher_check_connection(const char *filename, char *key, int key_sz, char *sql, int *user_version, char** journal_mode) {
- int rc;
- sqlcipher_sqlite3 *db = NULL;
- sqlcipher_sqlite3_stmt *statement = NULL;
- char *query_journal_mode = "PRAGMA journal_mode;";
- char *query_user_version = "PRAGMA user_version;";
-
- rc = sqlcipher_sqlite3_open(filename, &db);
- if(rc != SQLITE_OK) goto cleanup;
-
- rc = sqlcipher_sqlite3_key(db, key, key_sz);
- if(rc != SQLITE_OK) goto cleanup;
-
- rc = sqlcipher_sqlite3_exec(db, sql, NULL, NULL, NULL);
- if(rc != SQLITE_OK) goto cleanup;
-
- /* start by querying the user version.
- this will fail if the key is incorrect */
- rc = sqlcipher_sqlite3_prepare(db, query_user_version, -1, &statement, NULL);
- if(rc != SQLITE_OK) goto cleanup;
-
- rc = sqlcipher_sqlite3_step(statement);
- if(rc == SQLITE_ROW) {
- *user_version = sqlcipher_sqlite3_column_int(statement, 0);
- } else {
- goto cleanup;
- }
- sqlcipher_sqlite3_finalize(statement);
-
- rc = sqlcipher_sqlite3_prepare(db, query_journal_mode, -1, &statement, NULL);
- if(rc != SQLITE_OK) goto cleanup;
-
- rc = sqlcipher_sqlite3_step(statement);
- if(rc == SQLITE_ROW) {
- *journal_mode = sqlcipher_sqlite3_mprintf("%s", sqlcipher_sqlite3_column_text(statement, 0));
- } else {
- goto cleanup;
- }
- rc = SQLITE_OK;
- /* cleanup will finalize open statement */
-
-cleanup:
- if(statement) sqlcipher_sqlite3_finalize(statement);
- if(db) sqlcipher_sqlite3_close(db);
- return rc;
-}
-
-int sqlcipher_codec_ctx_integrity_check(codec_ctx *ctx, Parse *pParse, char *column) {
- Pgno page = 1;
- int rc = 0;
- char *result;
- unsigned char *hmac_out = NULL;
- sqlcipher_sqlite3_file *fd = sqlcipher_sqlite3PagerFile(ctx->pBt->pBt->pPager);
- i64 file_sz;
-
- Vdbe *v = sqlcipher_sqlite3GetVdbe(pParse);
- sqlcipher_sqlite3VdbeSetNumCols(v, 1);
- sqlcipher_sqlite3VdbeSetColName(v, 0, COLNAME_NAME, column, SQLITE_STATIC);
-
- if(fd == NULL || fd->pMethods == 0) {
- sqlcipher_sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, "database file is undefined", P4_TRANSIENT);
- sqlcipher_sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
- goto cleanup;
- }
-
- if(!(ctx->flags & CIPHER_FLAG_HMAC)) {
- sqlcipher_sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, "HMAC is not enabled, unable to integrity check", P4_TRANSIENT);
- sqlcipher_sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
- goto cleanup;
- }
-
- if((rc = sqlcipher_codec_key_derive(ctx)) != SQLITE_OK) {
- sqlcipher_sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, "unable to derive keys", P4_TRANSIENT);
- sqlcipher_sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
- goto cleanup;
- }
-
- sqlcipher_sqlite3OsFileSize(fd, &file_sz);
- hmac_out = sqlcipher_malloc(ctx->hmac_sz);
-
- for(page = 1; page <= file_sz / ctx->page_sz; page++) {
- int offset = (page - 1) * ctx->page_sz;
- int payload_sz = ctx->page_sz - ctx->reserve_sz + ctx->iv_sz;
- int read_sz = ctx->page_sz;
-
- /* skip integrity check on PAGER_MJ_PGNO since it will have no valid content */
- if(sqlcipher_sqlite3pager_is_mj_pgno(ctx->pBt->pBt->pPager, page)) continue;
-
- if(page==1) {
- int page1_offset = ctx->plaintext_header_sz ? ctx->plaintext_header_sz : FILE_HEADER_SZ;
- read_sz = read_sz - page1_offset;
- payload_sz = payload_sz - page1_offset;
- offset += page1_offset;
- }
-
- sqlcipher_memset(ctx->buffer, 0, ctx->page_sz);
- sqlcipher_memset(hmac_out, 0, ctx->hmac_sz);
- if(sqlcipher_sqlite3OsRead(fd, ctx->buffer, read_sz, offset) != SQLITE_OK) {
- result = sqlcipher_sqlite3_mprintf("error reading %d bytes from file page %d at offset %d\n", read_sz, page, offset);
- sqlcipher_sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, result, P4_DYNAMIC);
- sqlcipher_sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
- } else if(sqlcipher_page_hmac(ctx, ctx->read_ctx, page, ctx->buffer, payload_sz, hmac_out) != SQLITE_OK) {
- result = sqlcipher_sqlite3_mprintf("HMAC operation failed for page %d", page);
- sqlcipher_sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, result, P4_DYNAMIC);
- sqlcipher_sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
- } else if(sqlcipher_memcmp(ctx->buffer + payload_sz, hmac_out, ctx->hmac_sz) != 0) {
- result = sqlcipher_sqlite3_mprintf("HMAC verification failed for page %d", page);
- sqlcipher_sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, result, P4_DYNAMIC);
- sqlcipher_sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
- }
- }
-
- if(file_sz % ctx->page_sz != 0) {
- result = sqlcipher_sqlite3_mprintf("page %d has an invalid size of %lld bytes", page, file_sz - ((file_sz / ctx->page_sz) * ctx->page_sz));
- sqlcipher_sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, result, P4_DYNAMIC);
- sqlcipher_sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
- }
-
-cleanup:
- if(hmac_out != NULL) sqlcipher_free(hmac_out, ctx->hmac_sz);
- return SQLITE_OK;
-}
-
-int sqlcipher_codec_ctx_migrate(codec_ctx *ctx) {
- int i, pass_sz, keyspec_sz, nRes, user_version, rc, oflags;
- Db *pDb = 0;
- sqlcipher_sqlite3 *db = ctx->pBt->db;
- const char *db_filename = sqlcipher_sqlite3_db_filename(db, "main");
- char *set_user_version = NULL, *pass = NULL, *attach_command = NULL, *migrated_db_filename = NULL, *keyspec = NULL, *temp = NULL, *journal_mode = NULL, *set_journal_mode = NULL, *pragma_compat = NULL;
- Btree *pDest = NULL, *pSrc = NULL;
- sqlcipher_sqlite3_file *srcfile, *destfile;
-#if defined(_WIN32) || defined(SQLITE_OS_WINRT)
- LPWSTR w_db_filename = NULL, w_migrated_db_filename = NULL;
- int w_db_filename_sz = 0, w_migrated_db_filename_sz = 0;
+#ifdef SQLITE_DISABLE_INTRINSIC
+ "DISABLE_INTRINSIC",
#endif
- pass_sz = keyspec_sz = rc = user_version = 0;
-
- if(!db_filename || sqlcipher_sqlite3Strlen30(db_filename) < 1)
- goto cleanup; /* exit immediately if this is an in memory database */
-
- /* pull the provided password / key material off the current codec context */
- pass_sz = ctx->read_ctx->pass_sz;
- pass = sqlcipher_malloc(pass_sz+1);
- memset(pass, 0, pass_sz+1);
- memcpy(pass, ctx->read_ctx->pass, pass_sz);
-
- /* Version 4 - current, no upgrade required, so exit immediately */
- rc = sqlcipher_check_connection(db_filename, pass, pass_sz, "", &user_version, &journal_mode);
- if(rc == SQLITE_OK){
- CODEC_TRACE("No upgrade required - exiting\n");
- goto cleanup;
- }
-
- for(i = 3; i > 0; i--) {
- pragma_compat = sqlcipher_sqlite3_mprintf("PRAGMA cipher_compatibility = %d;", i);
- rc = sqlcipher_check_connection(db_filename, pass, pass_sz, pragma_compat, &user_version, &journal_mode);
- if(rc == SQLITE_OK) {
- CODEC_TRACE("Version %d format found\n", i);
- goto migrate;
- }
- if(pragma_compat) sqlcipher_free(pragma_compat, sqlcipher_sqlite3Strlen30(pragma_compat));
- pragma_compat = NULL;
- }
- /* if we exit the loop normally we failed to determine the version, this is an error */
- CODEC_TRACE("Upgrade format not determined\n");
- goto handle_error;
-
-migrate:
-
- temp = sqlcipher_sqlite3_mprintf("%s-migrated", db_filename);
- /* overallocate migrated_db_filename, because sqlcipher_sqlite3OsOpen will read past the null terminator
- * to determine whether the filename was URI formatted */
- migrated_db_filename = sqlcipher_malloc(sqlcipher_sqlite3Strlen30(temp)+2);
- memcpy(migrated_db_filename, temp, sqlcipher_sqlite3Strlen30(temp));
- sqlcipher_free(temp, sqlcipher_sqlite3Strlen30(temp));
-
- attach_command = sqlcipher_sqlite3_mprintf("ATTACH DATABASE '%s' as migrate;", migrated_db_filename, pass);
- set_user_version = sqlcipher_sqlite3_mprintf("PRAGMA migrate.user_version = %d;", user_version);
-
- rc = sqlcipher_sqlite3_exec(db, pragma_compat, NULL, NULL, NULL);
- if(rc != SQLITE_OK){
- CODEC_TRACE("set compatibility mode failed, error code %d\n", rc);
- goto handle_error;
- }
-
- /* force journal mode to DELETE, we will set it back later if different */
- rc = sqlcipher_sqlite3_exec(db, "PRAGMA journal_mode = delete;", NULL, NULL, NULL);
- if(rc != SQLITE_OK){
- CODEC_TRACE("force journal mode DELETE failed, error code %d\n", rc);
- goto handle_error;
- }
-
- rc = sqlcipher_sqlite3_exec(db, attach_command, NULL, NULL, NULL);
- if(rc != SQLITE_OK){
- CODEC_TRACE("attach failed, error code %d\n", rc);
- goto handle_error;
- }
-
- rc = sqlcipher_sqlite3_key_v2(db, "migrate", pass, pass_sz);
- if(rc != SQLITE_OK){
- CODEC_TRACE("keying attached database failed, error code %d\n", rc);
- goto handle_error;
- }
-
- rc = sqlcipher_sqlite3_exec(db, "SELECT sqlcipher_export('migrate');", NULL, NULL, NULL);
- if(rc != SQLITE_OK){
- CODEC_TRACE("sqlcipher_export failed, error code %d\n", rc);
- goto handle_error;
- }
-
- rc = sqlcipher_sqlite3_exec(db, set_user_version, NULL, NULL, NULL);
- if(rc != SQLITE_OK){
- CODEC_TRACE("set user version failed, error code %d\n", rc);
- goto handle_error;
- }
-
- if( !db->autoCommit ){
- CODEC_TRACE("cannot migrate from within a transaction");
- goto handle_error;
- }
- if( db->nVdbeActive>1 ){
- CODEC_TRACE("cannot migrate - SQL statements in progress");
- goto handle_error;
- }
-
- pDest = db->aDb[0].pBt;
- pDb = &(db->aDb[db->nDb-1]);
- pSrc = pDb->pBt;
-
- nRes = sqlcipher_sqlite3BtreeGetRequestedReserve(pSrc);
- /* unset the BTS_PAGESIZE_FIXED flag to avoid SQLITE_READONLY */
- pDest->pBt->btsFlags &= ~BTS_PAGESIZE_FIXED;
- rc = sqlcipher_sqlite3BtreeSetPageSize(pDest, default_page_size, nRes, 0);
- CODEC_TRACE("set btree page size to %d res %d rc %d\n", default_page_size, nRes, rc);
- if( rc!=SQLITE_OK ) goto handle_error;
-
- sqlcipher_sqlite3CodecGetKey(db, db->nDb - 1, (void**)&keyspec, &keyspec_sz);
- sqlcipher_sqlite3CodecAttach(db, 0, keyspec, keyspec_sz);
-
- srcfile = sqlcipher_sqlite3PagerFile(pSrc->pBt->pPager);
- destfile = sqlcipher_sqlite3PagerFile(pDest->pBt->pPager);
-
- sqlcipher_sqlite3OsClose(srcfile);
- sqlcipher_sqlite3OsClose(destfile);
-
-#if defined(_WIN32) || defined(SQLITE_OS_WINRT)
- CODEC_TRACE("performing windows MoveFileExA\n");
-
- w_db_filename_sz = MultiByteToWideChar(CP_UTF8, 0, (LPCCH) db_filename, -1, NULL, 0);
- w_db_filename = sqlcipher_malloc(w_db_filename_sz * sizeof(wchar_t));
- w_db_filename_sz = MultiByteToWideChar(CP_UTF8, 0, (LPCCH) db_filename, -1, (const LPWSTR) w_db_filename, w_db_filename_sz);
-
- w_migrated_db_filename_sz = MultiByteToWideChar(CP_UTF8, 0, (LPCCH) migrated_db_filename, -1, NULL, 0);
- w_migrated_db_filename = sqlcipher_malloc(w_migrated_db_filename_sz * sizeof(wchar_t));
- w_migrated_db_filename_sz = MultiByteToWideChar(CP_UTF8, 0, (LPCCH) migrated_db_filename, -1, (const LPWSTR) w_migrated_db_filename, w_migrated_db_filename_sz);
-
- if(!MoveFileExW(w_migrated_db_filename, w_db_filename, MOVEFILE_REPLACE_EXISTING)) {
- CODEC_TRACE("move error");
- rc = SQLITE_ERROR;
- CODEC_TRACE("error occurred while renaming %d\n", rc);
- goto handle_error;
- }
-#else
- CODEC_TRACE("performing POSIX rename\n");
- if ((rc = rename(migrated_db_filename, db_filename)) != 0) {
- CODEC_TRACE("error occurred while renaming %d\n", rc);
- goto handle_error;
- }
+#ifdef SQLITE_DISABLE_LFS
+ "DISABLE_LFS",
#endif
- CODEC_TRACE("renamed migration database %s to main database %s: %d\n", migrated_db_filename, db_filename, rc);
-
- rc = sqlcipher_sqlite3OsOpen(db->pVfs, migrated_db_filename, srcfile, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_MAIN_DB, &oflags);
- CODEC_TRACE("reopened migration database: %d\n", rc);
- if( rc!=SQLITE_OK ) goto handle_error;
-
- rc = sqlcipher_sqlite3OsOpen(db->pVfs, db_filename, destfile, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_MAIN_DB, &oflags);
- CODEC_TRACE("reopened main database: %d\n", rc);
- if( rc!=SQLITE_OK ) goto handle_error;
-
- sqlcipher_sqlite3pager_reset(pDest->pBt->pPager);
- CODEC_TRACE("reset pager\n");
-
- rc = sqlcipher_sqlite3_exec(db, "DETACH DATABASE migrate;", NULL, NULL, NULL);
- CODEC_TRACE("DETACH DATABASE called %d\n", rc);
- if(rc != SQLITE_OK) goto cleanup;
-
- rc = sqlcipher_sqlite3OsDelete(db->pVfs, migrated_db_filename, 0);
- CODEC_TRACE("deleted migration database: %d\n", rc);
- if( rc!=SQLITE_OK ) goto handle_error;
-
- sqlcipher_sqlite3ResetAllSchemasOfConnection(db);
- CODEC_TRACE("reset all schemas\n");
-
- set_journal_mode = sqlcipher_sqlite3_mprintf("PRAGMA journal_mode = %s;", journal_mode);
- rc = sqlcipher_sqlite3_exec(db, set_journal_mode, NULL, NULL, NULL);
- CODEC_TRACE("%s: %d\n", set_journal_mode, rc);
- if( rc!=SQLITE_OK ) goto handle_error;
-
- goto cleanup;
-
-handle_error:
- CODEC_TRACE("An error occurred attempting to migrate the database - last error %d\n", rc);
- rc = SQLITE_ERROR;
-
-cleanup:
- if(pass) sqlcipher_free(pass, pass_sz);
- if(attach_command) sqlcipher_free(attach_command, sqlcipher_sqlite3Strlen30(attach_command));
- if(migrated_db_filename) sqlcipher_free(migrated_db_filename, sqlcipher_sqlite3Strlen30(migrated_db_filename));
- if(set_user_version) sqlcipher_free(set_user_version, sqlcipher_sqlite3Strlen30(set_user_version));
- if(set_journal_mode) sqlcipher_free(set_journal_mode, sqlcipher_sqlite3Strlen30(set_journal_mode));
- if(journal_mode) sqlcipher_free(journal_mode, sqlcipher_sqlite3Strlen30(journal_mode));
- if(pragma_compat) sqlcipher_free(pragma_compat, sqlcipher_sqlite3Strlen30(pragma_compat));
-#if defined(_WIN32) || defined(SQLITE_OS_WINRT)
- if(w_db_filename) sqlcipher_free(w_db_filename, w_db_filename_sz);
- if(w_migrated_db_filename) sqlcipher_free(w_migrated_db_filename, w_migrated_db_filename_sz);
+#ifdef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
+ "DISABLE_PAGECACHE_OVERFLOW_STATS",
#endif
- return rc;
-}
-
-int sqlcipher_codec_add_random(codec_ctx *ctx, const char *zRight, int random_sz){
- const char *suffix = &zRight[random_sz-1];
- int n = random_sz - 3; /* adjust for leading x' and tailing ' */
- if (n > 0 &&
- sqlcipher_sqlite3StrNICmp((const char *)zRight ,"x'", 2) == 0 &&
- sqlcipher_sqlite3StrNICmp(suffix, "'", 1) == 0 &&
- n % 2 == 0) {
- int rc = 0;
- int buffer_sz = n / 2;
- unsigned char *random;
- const unsigned char *z = (const unsigned char *)zRight + 2; /* adjust lead offset of x' */
- CODEC_TRACE("sqlcipher_codec_add_random: using raw random blob from hex\n");
- random = sqlcipher_malloc(buffer_sz);
- memset(random, 0, buffer_sz);
- cipher_hex2bin(z, n, random);
- rc = ctx->provider->add_random(ctx->provider_ctx, random, buffer_sz);
- sqlcipher_free(random, buffer_sz);
- return rc;
- }
- return SQLITE_ERROR;
-}
-
-#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_DEPRECATED)
-static void sqlcipher_profile_callback(void *file, const char *sql, sqlcipher_sqlite3_uint64 run_time){
- FILE *f = (FILE*)file;
- double elapsed = run_time/1000000.0;
- if(f) fprintf(f, "Elapsed time:%.3f ms - %s\n", elapsed, sql);
-}
+#ifdef SQLITE_DISABLE_SKIPAHEAD_DISTINCT
+ "DISABLE_SKIPAHEAD_DISTINCT",
#endif
-
-int sqlcipher_cipher_profile(sqlcipher_sqlite3 *db, const char *destination){
-#if defined(SQLITE_OMIT_TRACE) || defined(SQLITE_OMIT_DEPRECATED)
- return SQLITE_ERROR;
-#else
- FILE *f;
- if(sqlcipher_sqlite3StrICmp(destination, "stdout") == 0){
- f = stdout;
- }else if(sqlcipher_sqlite3StrICmp(destination, "stderr") == 0){
- f = stderr;
- }else if(sqlcipher_sqlite3StrICmp(destination, "off") == 0){
- f = 0;
- }else{
-#if !defined(SQLCIPHER_PROFILE_USE_FOPEN) && (defined(_WIN32) && (__STDC_VERSION__ > 199901L) || defined(SQLITE_OS_WINRT))
- if(fopen_s(&f, destination, "a") != 0) return SQLITE_ERROR;
-#else
- if((f = fopen(destination, "a")) == 0) return SQLITE_ERROR;
+#ifdef SQLITE_ENABLE_8_3_NAMES
+ "ENABLE_8_3_NAMES=" CTIMEOPT_VAL(SQLITE_ENABLE_8_3_NAMES),
#endif
- }
- sqlcipher_sqlite3_profile(db, sqlcipher_profile_callback, f);
- return SQLITE_OK;
+#ifdef SQLITE_ENABLE_API_ARMOR
+ "ENABLE_API_ARMOR",
#endif
-}
-
-int sqlcipher_codec_fips_status(codec_ctx *ctx) {
- return ctx->provider->fips_status(ctx->provider_ctx);
-}
-
-const char* sqlcipher_codec_get_provider_version(codec_ctx *ctx) {
- return ctx->provider->get_provider_version(ctx->provider_ctx);
-}
-
+#ifdef SQLITE_ENABLE_ATOMIC_WRITE
+ "ENABLE_ATOMIC_WRITE",
#endif
-/* END SQLCIPHER */
-
-/************** End of crypto_impl.c *****************************************/
-/************** Begin file crypto_libtomcrypt.c ******************************/
-/*
-** SQLCipher
-** http://sqlcipher.net
-**
-** Copyright (c) 2008 - 2013, ZETETIC LLC
-** All rights reserved.
-**
-** Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in the
-** documentation and/or other materials provided with the distribution.
-** * Neither the name of the ZETETIC LLC nor the
-** names of its contributors may be used to endorse or promote products
-** derived from this software without specific prior written permission.
-**
-** THIS SOFTWARE IS PROVIDED BY ZETETIC LLC ''AS IS'' AND ANY
-** EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-** DISCLAIMED. IN NO EVENT SHALL ZETETIC LLC BE LIABLE FOR ANY
-** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-**
-*/
-/* BEGIN SQLCIPHER */
-#ifdef SQLITE_HAS_CODEC
-#ifdef SQLCIPHER_CRYPTO_LIBTOMCRYPT
-/* #include "sqliteInt.h" */
-/* #include "sqlcipher.h" */
-#include <tomcrypt.h>
-
-#define FORTUNA_MAX_SZ 32
-static prng_state prng;
-static volatile unsigned int ltc_init = 0;
-static volatile unsigned int ltc_ref_count = 0;
-
-#define LTC_CIPHER "rijndael"
-
-static int sqlcipher_ltc_add_random(void *ctx, void *buffer, int length) {
- int rc = 0;
- int data_to_read = length;
- int block_sz = data_to_read < FORTUNA_MAX_SZ ? data_to_read : FORTUNA_MAX_SZ;
- const unsigned char * data = (const unsigned char *)buffer;
-
- CODEC_TRACE_MUTEX("sqlcipher_ltc_add_random: entering SQLCIPHER_MUTEX_PROVIDER_RAND\n");
- sqlcipher_sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_RAND));
- CODEC_TRACE_MUTEX("sqlcipher_ltc_add_random: entered SQLCIPHER_MUTEX_PROVIDER_RAND\n");
-
- while(data_to_read > 0){
- rc = fortuna_add_entropy(data, block_sz, &prng);
- rc = rc != CRYPT_OK ? SQLITE_ERROR : SQLITE_OK;
- if(rc != SQLITE_OK){
- break;
- }
- data_to_read -= block_sz;
- data += block_sz;
- block_sz = data_to_read < FORTUNA_MAX_SZ ? data_to_read : FORTUNA_MAX_SZ;
- }
- fortuna_ready(&prng);
-
- CODEC_TRACE_MUTEX("sqlcipher_ltc_add_random: leaving SQLCIPHER_MUTEX_PROVIDER_RAND\n");
- sqlcipher_sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_RAND));
- CODEC_TRACE_MUTEX("sqlcipher_ltc_add_random: left SQLCIPHER_MUTEX_PROVIDER_RAND\n");
-
- return rc;
-}
-
-static int sqlcipher_ltc_activate(void *ctx) {
- unsigned char random_buffer[FORTUNA_MAX_SZ];
-
- CODEC_TRACE_MUTEX("sqlcipher_ltc_activate: entering SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n");
- sqlcipher_sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE));
- CODEC_TRACE_MUTEX("sqlcipher_ltc_activate: entered SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n");
-
- sqlcipher_memset(random_buffer, 0, FORTUNA_MAX_SZ);
- if(ltc_init == 0) {
- if(register_prng(&fortuna_desc) < 0) return SQLITE_ERROR;
- if(register_cipher(&rijndael_desc) < 0) return SQLITE_ERROR;
- if(register_hash(&sha512_desc) < 0) return SQLITE_ERROR;
- if(register_hash(&sha256_desc) < 0) return SQLITE_ERROR;
- if(register_hash(&sha1_desc) < 0) return SQLITE_ERROR;
- if(fortuna_start(&prng) != CRYPT_OK) {
- return SQLITE_ERROR;
- }
-
- ltc_init = 1;
- }
- ltc_ref_count++;
-
-#ifndef SQLCIPHER_TEST
- sqlcipher_sqlite3_randomness(FORTUNA_MAX_SZ, random_buffer);
+#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
+ "ENABLE_BATCH_ATOMIC_WRITE",
#endif
-
- if(sqlcipher_ltc_add_random(ctx, random_buffer, FORTUNA_MAX_SZ) != SQLITE_OK) {
- return SQLITE_ERROR;
- }
- sqlcipher_memset(random_buffer, 0, FORTUNA_MAX_SZ);
-
- CODEC_TRACE_MUTEX("sqlcipher_ltc_activate: leaving SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n");
- sqlcipher_sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE));
- CODEC_TRACE_MUTEX("sqlcipher_ltc_activate: left SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n");
-
- return SQLITE_OK;
-}
-
-static int sqlcipher_ltc_deactivate(void *ctx) {
- CODEC_TRACE_MUTEX("sqlcipher_ltc_deactivate: entering SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n");
- sqlcipher_sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE));
- CODEC_TRACE_MUTEX("sqlcipher_ltc_deactivate: entered SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n");
-
- ltc_ref_count--;
- if(ltc_ref_count == 0){
- fortuna_done(&prng);
- sqlcipher_memset((void *)&prng, 0, sizeof(prng));
- }
-
- CODEC_TRACE_MUTEX("sqlcipher_ltc_deactivate: leaving SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n");
- sqlcipher_sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE));
- CODEC_TRACE_MUTEX("sqlcipher_ltc_deactivate: left SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n");
-
- return SQLITE_OK;
-}
-
-static const char* sqlcipher_ltc_get_provider_name(void *ctx) {
- return "libtomcrypt";
-}
-
-static const char* sqlcipher_ltc_get_provider_version(void *ctx) {
- return SCRYPT;
-}
-
-static int sqlcipher_ltc_random(void *ctx, void *buffer, int length) {
- CODEC_TRACE_MUTEX("sqlcipher_ltc_random: entering SQLCIPHER_MUTEX_PROVIDER_RAND\n");
- sqlcipher_sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_RAND));
- CODEC_TRACE_MUTEX("sqlcipher_ltc_random: entered SQLCIPHER_MUTEX_PROVIDER_RAND\n");
-
- fortuna_read(buffer, length, &prng);
-
- CODEC_TRACE_MUTEX("sqlcipher_ltc_random: leaving SQLCIPHER_MUTEX_PROVIDER_RAND\n");
- sqlcipher_sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_RAND));
- CODEC_TRACE_MUTEX("sqlcipher_ltc_random: left SQLCIPHER_MUTEX_PROVIDER_RAND\n");
-
- return SQLITE_OK;
-}
-
-static int sqlcipher_ltc_hmac(void *ctx, int algorithm, unsigned char *hmac_key, int key_sz, unsigned char *in, int in_sz, unsigned char *in2, int in2_sz, unsigned char *out) {
- int rc, hash_idx;
- hmac_state hmac;
- unsigned long outlen;
- switch(algorithm) {
- case SQLCIPHER_HMAC_SHA1:
- hash_idx = find_hash("sha1");
- break;
- case SQLCIPHER_HMAC_SHA256:
- hash_idx = find_hash("sha256");
- break;
- case SQLCIPHER_HMAC_SHA512:
- hash_idx = find_hash("sha512");
- break;
- default:
- return SQLITE_ERROR;
- }
-
- if(hash_idx < 0) return SQLITE_ERROR;
- outlen = hash_descriptor[hash_idx].hashsize;
-
- if(in == NULL) return SQLITE_ERROR;
- if((rc = hmac_init(&hmac, hash_idx, hmac_key, key_sz)) != CRYPT_OK) return SQLITE_ERROR;
- if((rc = hmac_process(&hmac, in, in_sz)) != CRYPT_OK) return SQLITE_ERROR;
- if(in2 != NULL && (rc = hmac_process(&hmac, in2, in2_sz)) != CRYPT_OK) return SQLITE_ERROR;
- if((rc = hmac_done(&hmac, out, &outlen)) != CRYPT_OK) return SQLITE_ERROR;
- return SQLITE_OK;
-}
-
-static int sqlcipher_ltc_kdf(void *ctx, int algorithm, const unsigned char *pass, int pass_sz, unsigned char* salt, int salt_sz, int workfactor, int key_sz, unsigned char *key) {
- int rc, hash_idx;
- unsigned long outlen = key_sz;
-
- switch(algorithm) {
- case SQLCIPHER_HMAC_SHA1:
- hash_idx = find_hash("sha1");
- break;
- case SQLCIPHER_HMAC_SHA256:
- hash_idx = find_hash("sha256");
- break;
- case SQLCIPHER_HMAC_SHA512:
- hash_idx = find_hash("sha512");
- break;
- default:
- return SQLITE_ERROR;
- }
- if(hash_idx < 0) return SQLITE_ERROR;
-
- if((rc = pkcs_5_alg2(pass, pass_sz, salt, salt_sz,
- workfactor, hash_idx, key, &outlen)) != CRYPT_OK) {
- return SQLITE_ERROR;
- }
- return SQLITE_OK;
-}
-
-static const char* sqlcipher_ltc_get_cipher(void *ctx) {
- return "aes-256-cbc";
-}
-
-static int sqlcipher_ltc_cipher(void *ctx, int mode, unsigned char *key, int key_sz, unsigned char *iv, unsigned char *in, int in_sz, unsigned char *out) {
- int rc, cipher_idx;
- symmetric_CBC cbc;
-
- if((cipher_idx = find_cipher(LTC_CIPHER)) == -1) return SQLITE_ERROR;
- if((rc = cbc_start(cipher_idx, iv, key, key_sz, 0, &cbc)) != CRYPT_OK) return SQLITE_ERROR;
- rc = mode == 1 ? cbc_encrypt(in, out, in_sz, &cbc) : cbc_decrypt(in, out, in_sz, &cbc);
- if(rc != CRYPT_OK) return SQLITE_ERROR;
- cbc_done(&cbc);
- return SQLITE_OK;
-}
-
-static int sqlcipher_ltc_get_key_sz(void *ctx) {
- int cipher_idx = find_cipher(LTC_CIPHER);
- return cipher_descriptor[cipher_idx].max_key_length;
-}
-
-static int sqlcipher_ltc_get_iv_sz(void *ctx) {
- int cipher_idx = find_cipher(LTC_CIPHER);
- return cipher_descriptor[cipher_idx].block_length;
-}
-
-static int sqlcipher_ltc_get_block_sz(void *ctx) {
- int cipher_idx = find_cipher(LTC_CIPHER);
- return cipher_descriptor[cipher_idx].block_length;
-}
-
-static int sqlcipher_ltc_get_hmac_sz(void *ctx, int algorithm) {
- int hash_idx;
- switch(algorithm) {
- case SQLCIPHER_HMAC_SHA1:
- hash_idx = find_hash("sha1");
- break;
- case SQLCIPHER_HMAC_SHA256:
- hash_idx = find_hash("sha256");
- break;
- case SQLCIPHER_HMAC_SHA512:
- hash_idx = find_hash("sha512");
- break;
- default:
- return 0;
- }
-
- if(hash_idx < 0) return 0;
-
- return hash_descriptor[hash_idx].hashsize;
-}
-
-static int sqlcipher_ltc_ctx_init(void **ctx) {
- sqlcipher_ltc_activate(NULL);
- return SQLITE_OK;
-}
-
-static int sqlcipher_ltc_ctx_free(void **ctx) {
- sqlcipher_ltc_deactivate(&ctx);
- return SQLITE_OK;
-}
-
-static int sqlcipher_ltc_fips_status(void *ctx) {
- return 0;
-}
-
-int sqlcipher_ltc_setup(sqlcipher_provider *p) {
- p->activate = sqlcipher_ltc_activate;
- p->deactivate = sqlcipher_ltc_deactivate;
- p->get_provider_name = sqlcipher_ltc_get_provider_name;
- p->random = sqlcipher_ltc_random;
- p->hmac = sqlcipher_ltc_hmac;
- p->kdf = sqlcipher_ltc_kdf;
- p->cipher = sqlcipher_ltc_cipher;
- p->get_cipher = sqlcipher_ltc_get_cipher;
- p->get_key_sz = sqlcipher_ltc_get_key_sz;
- p->get_iv_sz = sqlcipher_ltc_get_iv_sz;
- p->get_block_sz = sqlcipher_ltc_get_block_sz;
- p->get_hmac_sz = sqlcipher_ltc_get_hmac_sz;
- p->ctx_init = sqlcipher_ltc_ctx_init;
- p->ctx_free = sqlcipher_ltc_ctx_free;
- p->add_random = sqlcipher_ltc_add_random;
- p->fips_status = sqlcipher_ltc_fips_status;
- p->get_provider_version = sqlcipher_ltc_get_provider_version;
- return SQLITE_OK;
-}
-
+#ifdef SQLITE_ENABLE_BYTECODE_VTAB
+ "ENABLE_BYTECODE_VTAB",
#endif
+#ifdef SQLITE_ENABLE_CEROD
+ "ENABLE_CEROD=" CTIMEOPT_VAL(SQLITE_ENABLE_CEROD),
#endif
-/* END SQLCIPHER */
-
-/************** End of crypto_libtomcrypt.c **********************************/
-/************** Begin file crypto_nss.c **************************************/
-/*
-** SQLCipher
-** http://sqlcipher.net
-**
-** Copyright (c) 2008 - 2013, ZETETIC LLC
-** All rights reserved.
-**
-** Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in the
-** documentation and/or other materials provided with the distribution.
-** * Neither the name of the ZETETIC LLC nor the
-** names of its contributors may be used to endorse or promote products
-** derived from this software without specific prior written permission.
-**
-** THIS SOFTWARE IS PROVIDED BY ZETETIC LLC ''AS IS'' AND ANY
-** EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-** DISCLAIMED. IN NO EVENT SHALL ZETETIC LLC BE LIABLE FOR ANY
-** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-**
-*/
-/* BEGIN SQLCIPHER */
-#ifdef SQLITE_HAS_CODEC
-#ifdef SQLCIPHER_CRYPTO_NSS
-/* #include "crypto.h" */
-/* #include "sqlcipher.h" */
-#include <nss/blapit.h>
-#include <nss/nss.h>
-#include <nss/pk11pub.h>
-
-static NSSInitContext* nss_init_context = NULL;
-static unsigned int nss_init_count = 0;
-
-int sqlcipher_nss_setup(sqlcipher_provider *p);
-
-static int sqlcipher_nss_activate(void *ctx) {
-
- CODEC_TRACE_MUTEX("sqlcipher_nss_activate: entering SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n");
- sqlcipher_sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE));
- CODEC_TRACE_MUTEX("sqlcipher_nss_activate: entered SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n");
- if (nss_init_context == NULL) {
- nss_init_context = NSS_InitContext("", "", "", "", NULL,
- NSS_INIT_READONLY | NSS_INIT_NOCERTDB | NSS_INIT_NOMODDB |
- NSS_INIT_FORCEOPEN | NSS_INIT_OPTIMIZESPACE | NSS_INIT_NOROOTINIT);
- }
- nss_init_count++;
- CODEC_TRACE_MUTEX("sqlcipher_nss_activate: leaving SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n");
- sqlcipher_sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE));
- CODEC_TRACE_MUTEX("sqlcipher_nss_activate: left SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n");
- return SQLITE_OK;
-}
-
-static int sqlcipher_nss_deactivate(void *ctx) {
- CODEC_TRACE_MUTEX("sqlcipher_nss_activate: entering SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n");
- sqlcipher_sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE));
- CODEC_TRACE_MUTEX("sqlcipher_nss_activate: entered SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n");
-
- nss_init_count--;
- if (nss_init_count == 0 && nss_init_context != NULL) {
- NSS_ShutdownContext(nss_init_context);
- nss_init_context = NULL;
- }
-
- CODEC_TRACE_MUTEX("sqlcipher_nss_activate: leaving SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n");
- sqlcipher_sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE));
- CODEC_TRACE_MUTEX("sqlcipher_nss_activate: left SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n");
- return SQLITE_OK;
-}
-
-static int sqlcipher_nss_add_random(void *ctx, void *buffer, int length) {
- return SQLITE_OK;
-}
-
-/* generate a defined number of random bytes */
-static int sqlcipher_nss_random (void *ctx, void *buffer, int length) {
- // PK11_GenerateRandom should be thread-safe.
- return (PK11_GenerateRandom((unsigned char *)buffer, length) == SECSuccess) ? SQLITE_OK : SQLITE_ERROR;
-}
-
-static const char* sqlcipher_nss_get_provider_name(void *ctx) {
- return "nss";
-}
-
-static const char* sqlcipher_nss_get_provider_version(void *ctx) {
- return NSS_GetVersion();
-}
-
-static const char* sqlcipher_nss_get_cipher(void *ctx) {
- return "aes-256-cbc";
-}
-
-static int sqlcipher_nss_get_key_sz(void *ctx) {
- return AES_256_KEY_LENGTH;
-}
-
-static int sqlcipher_nss_get_iv_sz(void *ctx) {
- return AES_BLOCK_SIZE;
-}
-
-static int sqlcipher_nss_get_block_sz(void *ctx) {
- return AES_BLOCK_SIZE;
-}
-
-static int sqlcipher_nss_get_hmac_sz(void *ctx, int algorithm) {
- switch(algorithm) {
- case SQLCIPHER_HMAC_SHA1:
- return SHA1_LENGTH;
- break;
- case SQLCIPHER_HMAC_SHA256:
- return SHA256_LENGTH;
- break;
- case SQLCIPHER_HMAC_SHA512:
- return SHA512_LENGTH;
- break;
- default:
- return 0;
- }
-}
-
-static int sqlcipher_nss_hmac(void *ctx, int algorithm, unsigned char *hmac_key, int key_sz, unsigned char *in, int in_sz, unsigned char *in2, int in2_sz, unsigned char *out) {
- int rc = SQLITE_OK;
- unsigned int length;
- unsigned int outLen;
- PK11Context* context = NULL;
- PK11SlotInfo * slot = NULL;
- PK11SymKey* symKey = NULL;
- if(in == NULL) goto error;
- CK_MECHANISM_TYPE mech;
- switch(algorithm) {
- case SQLCIPHER_HMAC_SHA1:
- mech = CKM_SHA_1_HMAC;
- break;
- case SQLCIPHER_HMAC_SHA256:
- mech = CKM_SHA256_HMAC;
- break;
- case SQLCIPHER_HMAC_SHA512:
- mech = CKM_SHA512_HMAC;
- break;
- default:
- goto error;
- }
- length = sqlcipher_nss_get_hmac_sz(ctx, algorithm);
- slot = PK11_GetInternalSlot();
- if (slot == NULL) goto error;
- SECItem keyItem;
- keyItem.data = hmac_key;
- keyItem.len = key_sz;
- symKey = PK11_ImportSymKey(slot, mech, PK11_OriginUnwrap,
- CKA_SIGN, &keyItem, NULL);
- if (symKey == NULL) goto error;
- SECItem noParams;
- noParams.data = 0;
- noParams.len = 0;
- context = PK11_CreateContextBySymKey(mech, CKA_SIGN, symKey, &noParams);
- if (context == NULL) goto error;
- if (PK11_DigestBegin(context) != SECSuccess) goto error;
- if (PK11_DigestOp(context, in, in_sz) != SECSuccess) goto error;
- if (in2 != NULL) {
- if (PK11_DigestOp(context, in2, in2_sz) != SECSuccess) goto error;
- }
- if (PK11_DigestFinal(context, out, &outLen, length) != SECSuccess) goto error;
-
- goto cleanup;
- error:
- rc = SQLITE_ERROR;
- cleanup:
- if (context) PK11_DestroyContext(context, PR_TRUE);
- if (symKey) PK11_FreeSymKey(symKey);
- if (slot) PK11_FreeSlot(slot);
- return rc;
-}
-
-static int sqlcipher_nss_kdf(void *ctx, int algorithm, const unsigned char *pass, int pass_sz, unsigned char* salt, int salt_sz, int workfactor, int key_sz, unsigned char *key) {
- int rc = SQLITE_OK;
- PK11SlotInfo * slot = NULL;
- SECAlgorithmID * algid = NULL;
- PK11SymKey* symKey = NULL;
- SECOidTag oidtag;
- switch(algorithm) {
- case SQLCIPHER_HMAC_SHA1:
- oidtag = SEC_OID_HMAC_SHA1;
- break;
- case SQLCIPHER_HMAC_SHA256:
- oidtag = SEC_OID_HMAC_SHA256;
- break;
- case SQLCIPHER_HMAC_SHA512:
- oidtag = SEC_OID_HMAC_SHA512;
- break;
- default:
- goto error;
- }
- SECItem secSalt;
- secSalt.data = salt;
- secSalt.len = salt_sz;
- // Always pass SEC_OID_HMAC_SHA1 (i.e. PBMAC1) as this parameter
- // is unused for key generation. It is currently only used
- // for PBKDF2 authentication or key (un)wrapping when specifying an
- // encryption algorithm (PBES2).
- algid = PK11_CreatePBEV2AlgorithmID(SEC_OID_PKCS5_PBKDF2, SEC_OID_HMAC_SHA1,
- oidtag, key_sz, workfactor, &secSalt);
- if (algid == NULL) goto error;
- slot = PK11_GetInternalSlot();
- if (slot == NULL) goto error;
- SECItem pwItem;
- pwItem.data = (unsigned char *) pass; // PK11_PBEKeyGen doesn't modify the key.
- pwItem.len = pass_sz;
- symKey = PK11_PBEKeyGen(slot, algid, &pwItem, PR_FALSE, NULL);
- if (symKey == NULL) goto error;
- if (PK11_ExtractKeyValue(symKey) != SECSuccess) goto error;
- // No need to free keyData as it is a buffer managed by symKey.
- SECItem* keyData = PK11_GetKeyData(symKey);
- if (keyData == NULL) goto error;
- memcpy(key, keyData->data, key_sz);
-
- goto cleanup;
- error:
- rc = SQLITE_ERROR;
- cleanup:
- if (slot) PK11_FreeSlot(slot);
- if (algid) SECOID_DestroyAlgorithmID(algid, PR_TRUE);
- if (symKey) PK11_FreeSymKey(symKey);
- return rc;
-}
-
-static int sqlcipher_nss_cipher(void *ctx, int mode, unsigned char *key, int key_sz, unsigned char *iv, unsigned char *in, int in_sz, unsigned char *out) {
- int rc = SQLITE_OK;
- PK11SlotInfo * slot = NULL;
- PK11SymKey* symKey = NULL;
- unsigned int outLen;
- SECItem params;
- params.data = iv;
- params.len = sqlcipher_nss_get_iv_sz(ctx);
- slot = PK11_GetInternalSlot();
- if (slot == NULL) goto error;
- SECItem keyItem;
- keyItem.data = key;
- keyItem.len = key_sz;
- symKey = PK11_ImportSymKey(slot, CKM_AES_CBC, PK11_OriginUnwrap,
- CKA_ENCRYPT, &keyItem, NULL);
- if (symKey == NULL) goto error;
- SECStatus rv;
- if (mode == CIPHER_ENCRYPT) {
- rv = PK11_Encrypt(symKey, CKM_AES_CBC, &params, out, &outLen,
- in_sz + 16, in, in_sz);
- } else {
- rv = PK11_Decrypt(symKey, CKM_AES_CBC, &params, out, &outLen,
- in_sz + 16, in, in_sz);
- }
- if (rv != SECSuccess) goto error;
-
- goto cleanup;
- error:
- rc = SQLITE_ERROR;
- cleanup:
- if (slot) PK11_FreeSlot(slot);
- if (symKey) PK11_FreeSymKey(symKey);
- return rc;
-}
-
-static int sqlcipher_nss_ctx_init(void **ctx) {
- sqlcipher_nss_activate(NULL);
- return SQLITE_OK;
-}
-
-static int sqlcipher_nss_ctx_free(void **ctx) {
- sqlcipher_nss_deactivate(NULL);
- return SQLITE_OK;
-}
-
-static int sqlcipher_nss_fips_status(void *ctx) {
- return 0;
-}
-
-int sqlcipher_nss_setup(sqlcipher_provider *p) {
- p->activate = sqlcipher_nss_activate;
- p->deactivate = sqlcipher_nss_deactivate;
- p->random = sqlcipher_nss_random;
- p->get_provider_name = sqlcipher_nss_get_provider_name;
- p->hmac = sqlcipher_nss_hmac;
- p->kdf = sqlcipher_nss_kdf;
- p->cipher = sqlcipher_nss_cipher;
- p->get_cipher = sqlcipher_nss_get_cipher;
- p->get_key_sz = sqlcipher_nss_get_key_sz;
- p->get_iv_sz = sqlcipher_nss_get_iv_sz;
- p->get_block_sz = sqlcipher_nss_get_block_sz;
- p->get_hmac_sz = sqlcipher_nss_get_hmac_sz;
- p->ctx_init = sqlcipher_nss_ctx_init;
- p->ctx_free = sqlcipher_nss_ctx_free;
- p->add_random = sqlcipher_nss_add_random;
- p->fips_status = sqlcipher_nss_fips_status;
- p->get_provider_version = sqlcipher_nss_get_provider_version;
- return SQLITE_OK;
-}
-
+#ifdef SQLITE_ENABLE_COLUMN_METADATA
+ "ENABLE_COLUMN_METADATA",
#endif
+#ifdef SQLITE_ENABLE_COLUMN_USED_MASK
+ "ENABLE_COLUMN_USED_MASK",
#endif
-/* END SQLCIPHER */
-
-/************** End of crypto_nss.c ******************************************/
-/************** Begin file crypto_openssl.c **********************************/
-/*
-** SQLCipher
-** http://sqlcipher.net
-**
-** Copyright (c) 2008 - 2013, ZETETIC LLC
-** All rights reserved.
-**
-** Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in the
-** documentation and/or other materials provided with the distribution.
-** * Neither the name of the ZETETIC LLC nor the
-** names of its contributors may be used to endorse or promote products
-** derived from this software without specific prior written permission.
-**
-** THIS SOFTWARE IS PROVIDED BY ZETETIC LLC ''AS IS'' AND ANY
-** EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-** DISCLAIMED. IN NO EVENT SHALL ZETETIC LLC BE LIABLE FOR ANY
-** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-**
-*/
-/* BEGIN SQLCIPHER */
-#ifdef SQLITE_HAS_CODEC
-#ifdef SQLCIPHER_CRYPTO_OPENSSL
-/* #include "sqliteInt.h" */
-/* #include "crypto.h" */
-/* #include "sqlcipher.h" */
-#include <openssl/rand.h>
-#include <openssl/evp.h>
-#include <openssl/objects.h>
-#include <openssl/hmac.h>
-#include <openssl/err.h>
-
-static unsigned int openssl_init_count = 0;
-
-#if (defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x10100000L) || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L)
-static HMAC_CTX *HMAC_CTX_new(void)
-{
- HMAC_CTX *ctx = OPENSSL_malloc(sizeof(*ctx));
- if (ctx != NULL) {
- HMAC_CTX_init(ctx);
- }
- return ctx;
-}
-
-/* Per 1.1.0 (https://wiki.openssl.org/index.php/1.1_API_Changes)
- HMAC_CTX_free should call HMAC_CTX_cleanup, then EVP_MD_CTX_Cleanup.
- HMAC_CTX_cleanup internally calls EVP_MD_CTX_cleanup so these
- calls are not needed. */
-static void HMAC_CTX_free(HMAC_CTX *ctx)
-{
- if (ctx != NULL) {
- HMAC_CTX_cleanup(ctx);
- OPENSSL_free(ctx);
- }
-}
+#ifdef SQLITE_ENABLE_COSTMULT
+ "ENABLE_COSTMULT",
#endif
-
-static int sqlcipher_openssl_add_random(void *ctx, void *buffer, int length) {
-#ifndef SQLCIPHER_OPENSSL_NO_MUTEX_RAND
- CODEC_TRACE_MUTEX("sqlcipher_openssl_add_random: entering SQLCIPHER_MUTEX_PROVIDER_RAND\n");
- sqlcipher_sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_RAND));
- CODEC_TRACE_MUTEX("sqlcipher_openssl_add_random: entered SQLCIPHER_MUTEX_PROVIDER_RAND\n");
+#ifdef SQLITE_ENABLE_CURSOR_HINTS
+ "ENABLE_CURSOR_HINTS",
#endif
- RAND_add(buffer, length, 0);
-#ifndef SQLCIPHER_OPENSSL_NO_MUTEX_RAND
- CODEC_TRACE_MUTEX("sqlcipher_openssl_add_random: leaving SQLCIPHER_MUTEX_PROVIDER_RAND\n");
- sqlcipher_sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_RAND));
- CODEC_TRACE_MUTEX("sqlcipher_openssl_add_random: left SQLCIPHER_MUTEX_PROVIDER_RAND\n");
+#ifdef SQLITE_ENABLE_DBPAGE_VTAB
+ "ENABLE_DBPAGE_VTAB",
#endif
- return SQLITE_OK;
-}
-
-#define OPENSSL_CIPHER EVP_aes_256_cbc()
-
-
-/* activate and initialize sqlcipher. Most importantly, this will automatically
- intialize OpenSSL's EVP system if it hasn't already be externally. Note that
- this function may be called multiple times as new codecs are intiialized.
- Thus it performs some basic counting to ensure that only the last and final
- sqlcipher_openssl_deactivate() will free the EVP structures.
-*/
-static int sqlcipher_openssl_activate(void *ctx) {
- /* initialize openssl and increment the internal init counter
- but only if it hasn't been initalized outside of SQLCipher by this program
- e.g. on startup */
-
- CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: entering SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n");
- sqlcipher_sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE));
- CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: entered SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n");
-
-#ifdef SQLCIPHER_FIPS
- if(!FIPS_mode()){
- if(!FIPS_mode_set(1)){
- unsigned long err = 0;
- ERR_load_crypto_strings();
-#ifdef __ANDROID__
- while((err = ERR_get_error()) != 0) {
- __android_log_print(ANDROID_LOG_ERROR, "sqlcipher","error: %lx. %s.", err, ERR_error_string(err, NULL));
- }
-#else
- ERR_print_errors_fp(stderr);
+#ifdef SQLITE_ENABLE_DBSTAT_VTAB
+ "ENABLE_DBSTAT_VTAB",
#endif
- }
- }
+#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
+ "ENABLE_EXPENSIVE_ASSERT",
#endif
-
- openssl_init_count++;
- CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: leaving SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n");
- sqlcipher_sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE));
- CODEC_TRACE_MUTEX("sqlcipher_openssl_activate: left SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n");
- return SQLITE_OK;
-}
-
-/* deactivate SQLCipher, most imporantly decremeting the activation count and
- freeing the EVP structures on the final deactivation to ensure that
- OpenSSL memory is cleaned up */
-static int sqlcipher_openssl_deactivate(void *ctx) {
- CODEC_TRACE_MUTEX("sqlcipher_openssl_deactivate: entering SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n");
- sqlcipher_sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE));
- CODEC_TRACE_MUTEX("sqlcipher_openssl_deactivate: entered SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n");
-
- openssl_init_count--;
-
- CODEC_TRACE_MUTEX("sqlcipher_openssl_deactivate: leaving SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n");
- sqlcipher_sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE));
- CODEC_TRACE_MUTEX("sqlcipher_openssl_deactivate: left SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n");
- return SQLITE_OK;
-}
-
-static const char* sqlcipher_openssl_get_provider_name(void *ctx) {
- return "openssl";
-}
-
-static const char* sqlcipher_openssl_get_provider_version(void *ctx) {
- return OPENSSL_VERSION_TEXT;
-}
-
-/* generate a defined number of random bytes */
-static int sqlcipher_openssl_random (void *ctx, void *buffer, int length) {
- int rc = 0;
- /* concurrent calls to RAND_bytes can cause a crash under some openssl versions when a
- naive application doesn't use CRYPTO_set_locking_callback and
- CRYPTO_THREADID_set_callback to ensure openssl thread safety.
- This is simple workaround to prevent this common crash
- but a more proper solution is that applications setup platform-appropriate
- thread saftey in openssl externally */
-#ifndef SQLCIPHER_OPENSSL_NO_MUTEX_RAND
- CODEC_TRACE_MUTEX("sqlcipher_openssl_random: entering SQLCIPHER_MUTEX_PROVIDER_RAND\n");
- sqlcipher_sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_RAND));
- CODEC_TRACE_MUTEX("sqlcipher_openssl_random: entered SQLCIPHER_MUTEX_PROVIDER_RAND\n");
+#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
+ "ENABLE_EXPLAIN_COMMENTS",
#endif
- rc = RAND_bytes((unsigned char *)buffer, length);
-#ifndef SQLCIPHER_OPENSSL_NO_MUTEX_RAND
- CODEC_TRACE_MUTEX("sqlcipher_openssl_random: leaving SQLCIPHER_MUTEX_PROVIDER_RAND\n");
- sqlcipher_sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_RAND));
- CODEC_TRACE_MUTEX("sqlcipher_openssl_random: left SQLCIPHER_MUTEX_PROVIDER_RAND\n");
+#ifdef SQLITE_ENABLE_FTS3
+ "ENABLE_FTS3",
#endif
- return (rc == 1) ? SQLITE_OK : SQLITE_ERROR;
-}
-
-static int sqlcipher_openssl_hmac(void *ctx, int algorithm, unsigned char *hmac_key, int key_sz, unsigned char *in, int in_sz, unsigned char *in2, int in2_sz, unsigned char *out) {
- unsigned int outlen;
- int rc = SQLITE_OK;
- HMAC_CTX* hctx = NULL;
-
- if(in == NULL) goto error;
-
- hctx = HMAC_CTX_new();
- if(hctx == NULL) goto error;
-
- switch(algorithm) {
- case SQLCIPHER_HMAC_SHA1:
- if(!HMAC_Init_ex(hctx, hmac_key, key_sz, EVP_sha1(), NULL)) goto error;
- break;
- case SQLCIPHER_HMAC_SHA256:
- if(!HMAC_Init_ex(hctx, hmac_key, key_sz, EVP_sha256(), NULL)) goto error;
- break;
- case SQLCIPHER_HMAC_SHA512:
- if(!HMAC_Init_ex(hctx, hmac_key, key_sz, EVP_sha512(), NULL)) goto error;
- break;
- default:
- goto error;
- }
-
- if(!HMAC_Update(hctx, in, in_sz)) goto error;
- if(in2 != NULL) {
- if(!HMAC_Update(hctx, in2, in2_sz)) goto error;
- }
- if(!HMAC_Final(hctx, out, &outlen)) goto error;
-
- goto cleanup;
-error:
- rc = SQLITE_ERROR;
-cleanup:
- if(hctx) HMAC_CTX_free(hctx);
- return rc;
-}
-
-static int sqlcipher_openssl_kdf(void *ctx, int algorithm, const unsigned char *pass, int pass_sz, unsigned char* salt, int salt_sz, int workfactor, int key_sz, unsigned char *key) {
- int rc = SQLITE_OK;
-
- switch(algorithm) {
- case SQLCIPHER_HMAC_SHA1:
- if(!PKCS5_PBKDF2_HMAC((const char *)pass, pass_sz, salt, salt_sz, workfactor, EVP_sha1(), key_sz, key)) goto error;
- break;
- case SQLCIPHER_HMAC_SHA256:
- if(!PKCS5_PBKDF2_HMAC((const char *)pass, pass_sz, salt, salt_sz, workfactor, EVP_sha256(), key_sz, key)) goto error;
- break;
- case SQLCIPHER_HMAC_SHA512:
- if(!PKCS5_PBKDF2_HMAC((const char *)pass, pass_sz, salt, salt_sz, workfactor, EVP_sha512(), key_sz, key)) goto error;
- break;
- default:
- return SQLITE_ERROR;
- }
-
- goto cleanup;
-error:
- rc = SQLITE_ERROR;
-cleanup:
- return rc;
-}
-
-static int sqlcipher_openssl_cipher(void *ctx, int mode, unsigned char *key, int key_sz, unsigned char *iv, unsigned char *in, int in_sz, unsigned char *out) {
- int tmp_csz, csz, rc = SQLITE_OK;
- EVP_CIPHER_CTX* ectx = EVP_CIPHER_CTX_new();
- if(ectx == NULL) goto error;
- if(!EVP_CipherInit_ex(ectx, OPENSSL_CIPHER, NULL, NULL, NULL, mode)) goto error;
- if(!EVP_CIPHER_CTX_set_padding(ectx, 0)) goto error; /* no padding */
- if(!EVP_CipherInit_ex(ectx, NULL, NULL, key, iv, mode)) goto error;
- if(!EVP_CipherUpdate(ectx, out, &tmp_csz, in, in_sz)) goto error;
- csz = tmp_csz;
- out += tmp_csz;
- if(!EVP_CipherFinal_ex(ectx, out, &tmp_csz)) goto error;
- csz += tmp_csz;
- assert(in_sz == csz);
-
- goto cleanup;
-error:
- rc = SQLITE_ERROR;
-cleanup:
- if(ectx) EVP_CIPHER_CTX_free(ectx);
- return rc;
-}
-
-static const char* sqlcipher_openssl_get_cipher(void *ctx) {
- return OBJ_nid2sn(EVP_CIPHER_nid(OPENSSL_CIPHER));
-}
-
-static int sqlcipher_openssl_get_key_sz(void *ctx) {
- return EVP_CIPHER_key_length(OPENSSL_CIPHER);
-}
-
-static int sqlcipher_openssl_get_iv_sz(void *ctx) {
- return EVP_CIPHER_iv_length(OPENSSL_CIPHER);
-}
-
-static int sqlcipher_openssl_get_block_sz(void *ctx) {
- return EVP_CIPHER_block_size(OPENSSL_CIPHER);
-}
-
-static int sqlcipher_openssl_get_hmac_sz(void *ctx, int algorithm) {
- switch(algorithm) {
- case SQLCIPHER_HMAC_SHA1:
- return EVP_MD_size(EVP_sha1());
- break;
- case SQLCIPHER_HMAC_SHA256:
- return EVP_MD_size(EVP_sha256());
- break;
- case SQLCIPHER_HMAC_SHA512:
- return EVP_MD_size(EVP_sha512());
- break;
- default:
- return 0;
- }
-}
-
-static int sqlcipher_openssl_ctx_init(void **ctx) {
- return sqlcipher_openssl_activate(*ctx);
-}
-
-static int sqlcipher_openssl_ctx_free(void **ctx) {
- return sqlcipher_openssl_deactivate(NULL);
-}
-
-static int sqlcipher_openssl_fips_status(void *ctx) {
-#ifdef SQLCIPHER_FIPS
- return FIPS_mode();
-#else
- return 0;
+#ifdef SQLITE_ENABLE_FTS3_PARENTHESIS
+ "ENABLE_FTS3_PARENTHESIS",
#endif
-}
-
-int sqlcipher_openssl_setup(sqlcipher_provider *p) {
- p->activate = sqlcipher_openssl_activate;
- p->deactivate = sqlcipher_openssl_deactivate;
- p->get_provider_name = sqlcipher_openssl_get_provider_name;
- p->random = sqlcipher_openssl_random;
- p->hmac = sqlcipher_openssl_hmac;
- p->kdf = sqlcipher_openssl_kdf;
- p->cipher = sqlcipher_openssl_cipher;
- p->get_cipher = sqlcipher_openssl_get_cipher;
- p->get_key_sz = sqlcipher_openssl_get_key_sz;
- p->get_iv_sz = sqlcipher_openssl_get_iv_sz;
- p->get_block_sz = sqlcipher_openssl_get_block_sz;
- p->get_hmac_sz = sqlcipher_openssl_get_hmac_sz;
- p->ctx_init = sqlcipher_openssl_ctx_init;
- p->ctx_free = sqlcipher_openssl_ctx_free;
- p->add_random = sqlcipher_openssl_add_random;
- p->fips_status = sqlcipher_openssl_fips_status;
- p->get_provider_version = sqlcipher_openssl_get_provider_version;
- return SQLITE_OK;
-}
-
+#ifdef SQLITE_ENABLE_FTS3_TOKENIZER
+ "ENABLE_FTS3_TOKENIZER",
#endif
+#ifdef SQLITE_ENABLE_FTS4
+ "ENABLE_FTS4",
+#endif
+#ifdef SQLITE_ENABLE_FTS5
+ "ENABLE_FTS5",
+#endif
+#ifdef SQLITE_ENABLE_GEOPOLY
+ "ENABLE_GEOPOLY",
+#endif
+#ifdef SQLITE_ENABLE_HIDDEN_COLUMNS
+ "ENABLE_HIDDEN_COLUMNS",
+#endif
+#ifdef SQLITE_ENABLE_ICU
+ "ENABLE_ICU",
+#endif
+#ifdef SQLITE_ENABLE_IOTRACE
+ "ENABLE_IOTRACE",
+#endif
+#ifdef SQLITE_ENABLE_LOAD_EXTENSION
+ "ENABLE_LOAD_EXTENSION",
+#endif
+#ifdef SQLITE_ENABLE_LOCKING_STYLE
+ "ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE),
+#endif
+#ifdef SQLITE_ENABLE_MATH_FUNCTIONS
+ "ENABLE_MATH_FUNCTIONS",
+#endif
+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
+ "ENABLE_MEMORY_MANAGEMENT",
+#endif
+#ifdef SQLITE_ENABLE_MEMSYS3
+ "ENABLE_MEMSYS3",
+#endif
+#ifdef SQLITE_ENABLE_MEMSYS5
+ "ENABLE_MEMSYS5",
+#endif
+#ifdef SQLITE_ENABLE_MULTIPLEX
+ "ENABLE_MULTIPLEX",
+#endif
+#ifdef SQLITE_ENABLE_NORMALIZE
+ "ENABLE_NORMALIZE",
+#endif
+#ifdef SQLITE_ENABLE_NULL_TRIM
+ "ENABLE_NULL_TRIM",
+#endif
+#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
+ "ENABLE_OFFSET_SQL_FUNC",
+#endif
+#ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK
+ "ENABLE_OVERSIZE_CELL_CHECK",
+#endif
+#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
+ "ENABLE_PREUPDATE_HOOK",
+#endif
+#ifdef SQLITE_ENABLE_QPSG
+ "ENABLE_QPSG",
+#endif
+#ifdef SQLITE_ENABLE_RBU
+ "ENABLE_RBU",
+#endif
+#ifdef SQLITE_ENABLE_RTREE
+ "ENABLE_RTREE",
+#endif
+#ifdef SQLITE_ENABLE_SESSION
+ "ENABLE_SESSION",
+#endif
+#ifdef SQLITE_ENABLE_SNAPSHOT
+ "ENABLE_SNAPSHOT",
+#endif
+#ifdef SQLITE_ENABLE_SORTER_REFERENCES
+ "ENABLE_SORTER_REFERENCES",
+#endif
+#ifdef SQLITE_ENABLE_SQLLOG
+ "ENABLE_SQLLOG",
+#endif
+#ifdef SQLITE_ENABLE_STAT4
+ "ENABLE_STAT4",
+#endif
+#ifdef SQLITE_ENABLE_STMTVTAB
+ "ENABLE_STMTVTAB",
+#endif
+#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
+ "ENABLE_STMT_SCANSTATUS",
+#endif
+#ifdef SQLITE_ENABLE_TREETRACE
+ "ENABLE_TREETRACE",
+#endif
+#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
+ "ENABLE_UNKNOWN_SQL_FUNCTION",
+#endif
+#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
+ "ENABLE_UNLOCK_NOTIFY",
+#endif
+#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
+ "ENABLE_UPDATE_DELETE_LIMIT",
+#endif
+#ifdef SQLITE_ENABLE_URI_00_ERROR
+ "ENABLE_URI_00_ERROR",
+#endif
+#ifdef SQLITE_ENABLE_VFSTRACE
+ "ENABLE_VFSTRACE",
+#endif
+#ifdef SQLITE_ENABLE_WHERETRACE
+ "ENABLE_WHERETRACE",
+#endif
+#ifdef SQLITE_ENABLE_ZIPVFS
+ "ENABLE_ZIPVFS",
+#endif
+#ifdef SQLITE_EXPLAIN_ESTIMATED_ROWS
+ "EXPLAIN_ESTIMATED_ROWS",
+#endif
+#ifdef SQLITE_EXTRA_IFNULLROW
+ "EXTRA_IFNULLROW",
+#endif
+#ifdef SQLITE_EXTRA_INIT
+ "EXTRA_INIT=" CTIMEOPT_VAL(SQLITE_EXTRA_INIT),
+#endif
+#ifdef SQLITE_EXTRA_SHUTDOWN
+ "EXTRA_SHUTDOWN=" CTIMEOPT_VAL(SQLITE_EXTRA_SHUTDOWN),
+#endif
+#ifdef SQLITE_FTS3_MAX_EXPR_DEPTH
+ "FTS3_MAX_EXPR_DEPTH=" CTIMEOPT_VAL(SQLITE_FTS3_MAX_EXPR_DEPTH),
+#endif
+#ifdef SQLITE_FTS5_ENABLE_TEST_MI
+ "FTS5_ENABLE_TEST_MI",
+#endif
+#ifdef SQLITE_FTS5_NO_WITHOUT_ROWID
+ "FTS5_NO_WITHOUT_ROWID",
#endif
-/* END SQLCIPHER */
-
-/************** End of crypto_openssl.c **************************************/
-/************** Begin file crypto_cc.c ***************************************/
-/*
-** SQLCipher
-** http://sqlcipher.net
-**
-** Copyright (c) 2008 - 2013, ZETETIC LLC
-** All rights reserved.
-**
-** Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in the
-** documentation and/or other materials provided with the distribution.
-** * Neither the name of the ZETETIC LLC nor the
-** names of its contributors may be used to endorse or promote products
-** derived from this software without specific prior written permission.
-**
-** THIS SOFTWARE IS PROVIDED BY ZETETIC LLC ''AS IS'' AND ANY
-** EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-** DISCLAIMED. IN NO EVENT SHALL ZETETIC LLC BE LIABLE FOR ANY
-** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-**
-*/
/* BEGIN SQLCIPHER */
-#ifdef SQLITE_HAS_CODEC
-#ifdef SQLCIPHER_CRYPTO_CC
-/* #include "crypto.h" */
-/* #include "sqlcipher.h" */
-#include <CommonCrypto/CommonCrypto.h>
-#include <Security/SecRandom.h>
-#include <CoreFoundation/CoreFoundation.h>
-
-int sqlcipher_cc_setup(sqlcipher_provider *p);
-
-static int sqlcipher_cc_add_random(void *ctx, void *buffer, int length) {
- return SQLITE_OK;
-}
-
-/* generate a defined number of random bytes */
-static int sqlcipher_cc_random (void *ctx, void *buffer, int length) {
- return (SecRandomCopyBytes(kSecRandomDefault, length, (uint8_t *)buffer) == kCCSuccess) ? SQLITE_OK : SQLITE_ERROR;
-}
-
-static const char* sqlcipher_cc_get_provider_name(void *ctx) {
- return "commoncrypto";
-}
-
-static const char* sqlcipher_cc_get_provider_version(void *ctx) {
-#if TARGET_OS_MAC
- CFTypeRef version;
- CFBundleRef bundle = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.security"));
- if(bundle == NULL) {
- return "unknown";
- }
- version = CFBundleGetValueForInfoDictionaryKey(bundle, CFSTR("CFBundleShortVersionString"));
- return CFStringGetCStringPtr(version, kCFStringEncodingUTF8);
+#if SQLITE_HAS_CODEC
+ "HAS_CODEC",
+#endif
+/* END SQLCIPHER */
+#if HAVE_ISNAN || SQLITE_HAVE_ISNAN
+ "HAVE_ISNAN",
+#endif
+#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
+# if SQLITE_HOMEGROWN_RECURSIVE_MUTEX != 1
+ "HOMEGROWN_RECURSIVE_MUTEX=" CTIMEOPT_VAL(SQLITE_HOMEGROWN_RECURSIVE_MUTEX),
+# endif
+#endif
+#ifdef SQLITE_IGNORE_AFP_LOCK_ERRORS
+ "IGNORE_AFP_LOCK_ERRORS",
+#endif
+#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
+ "IGNORE_FLOCK_LOCK_ERRORS",
+#endif
+#ifdef SQLITE_INLINE_MEMCPY
+ "INLINE_MEMCPY",
+#endif
+#ifdef SQLITE_INT64_TYPE
+ "INT64_TYPE",
+#endif
+#ifdef SQLITE_INTEGRITY_CHECK_ERROR_MAX
+ "INTEGRITY_CHECK_ERROR_MAX=" CTIMEOPT_VAL(SQLITE_INTEGRITY_CHECK_ERROR_MAX),
+#endif
+#ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS
+ "LIKE_DOESNT_MATCH_BLOBS",
+#endif
+#ifdef SQLITE_LOCK_TRACE
+ "LOCK_TRACE",
+#endif
+#ifdef SQLITE_LOG_CACHE_SPILL
+ "LOG_CACHE_SPILL",
+#endif
+#ifdef SQLITE_MALLOC_SOFT_LIMIT
+ "MALLOC_SOFT_LIMIT=" CTIMEOPT_VAL(SQLITE_MALLOC_SOFT_LIMIT),
+#endif
+#ifdef SQLITE_MAX_ATTACHED
+ "MAX_ATTACHED=" CTIMEOPT_VAL(SQLITE_MAX_ATTACHED),
+#endif
+#ifdef SQLITE_MAX_COLUMN
+ "MAX_COLUMN=" CTIMEOPT_VAL(SQLITE_MAX_COLUMN),
+#endif
+#ifdef SQLITE_MAX_COMPOUND_SELECT
+ "MAX_COMPOUND_SELECT=" CTIMEOPT_VAL(SQLITE_MAX_COMPOUND_SELECT),
+#endif
+#ifdef SQLITE_MAX_DEFAULT_PAGE_SIZE
+ "MAX_DEFAULT_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_DEFAULT_PAGE_SIZE),
+#endif
+#ifdef SQLITE_MAX_EXPR_DEPTH
+ "MAX_EXPR_DEPTH=" CTIMEOPT_VAL(SQLITE_MAX_EXPR_DEPTH),
+#endif
+#ifdef SQLITE_MAX_FUNCTION_ARG
+ "MAX_FUNCTION_ARG=" CTIMEOPT_VAL(SQLITE_MAX_FUNCTION_ARG),
+#endif
+#ifdef SQLITE_MAX_LENGTH
+ "MAX_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_LENGTH),
+#endif
+#ifdef SQLITE_MAX_LIKE_PATTERN_LENGTH
+ "MAX_LIKE_PATTERN_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_LIKE_PATTERN_LENGTH),
+#endif
+#ifdef SQLITE_MAX_MEMORY
+ "MAX_MEMORY=" CTIMEOPT_VAL(SQLITE_MAX_MEMORY),
+#endif
+#ifdef SQLITE_MAX_MMAP_SIZE
+ "MAX_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_MMAP_SIZE),
+#endif
+#ifdef SQLITE_MAX_MMAP_SIZE_
+ "MAX_MMAP_SIZE_=" CTIMEOPT_VAL(SQLITE_MAX_MMAP_SIZE_),
+#endif
+#ifdef SQLITE_MAX_PAGE_COUNT
+ "MAX_PAGE_COUNT=" CTIMEOPT_VAL(SQLITE_MAX_PAGE_COUNT),
+#endif
+#ifdef SQLITE_MAX_PAGE_SIZE
+ "MAX_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_PAGE_SIZE),
+#endif
+#ifdef SQLITE_MAX_SCHEMA_RETRY
+ "MAX_SCHEMA_RETRY=" CTIMEOPT_VAL(SQLITE_MAX_SCHEMA_RETRY),
+#endif
+#ifdef SQLITE_MAX_SQL_LENGTH
+ "MAX_SQL_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_SQL_LENGTH),
+#endif
+#ifdef SQLITE_MAX_TRIGGER_DEPTH
+ "MAX_TRIGGER_DEPTH=" CTIMEOPT_VAL(SQLITE_MAX_TRIGGER_DEPTH),
+#endif
+#ifdef SQLITE_MAX_VARIABLE_NUMBER
+ "MAX_VARIABLE_NUMBER=" CTIMEOPT_VAL(SQLITE_MAX_VARIABLE_NUMBER),
+#endif
+#ifdef SQLITE_MAX_VDBE_OP
+ "MAX_VDBE_OP=" CTIMEOPT_VAL(SQLITE_MAX_VDBE_OP),
+#endif
+#ifdef SQLITE_MAX_WORKER_THREADS
+ "MAX_WORKER_THREADS=" CTIMEOPT_VAL(SQLITE_MAX_WORKER_THREADS),
+#endif
+#ifdef SQLITE_MEMDEBUG
+ "MEMDEBUG",
+#endif
+#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT
+ "MIXED_ENDIAN_64BIT_FLOAT",
+#endif
+#ifdef SQLITE_MMAP_READWRITE
+ "MMAP_READWRITE",
+#endif
+#ifdef SQLITE_MUTEX_NOOP
+ "MUTEX_NOOP",
+#endif
+#ifdef SQLITE_MUTEX_OMIT
+ "MUTEX_OMIT",
+#endif
+#ifdef SQLITE_MUTEX_PTHREADS
+ "MUTEX_PTHREADS",
+#endif
+#ifdef SQLITE_MUTEX_W32
+ "MUTEX_W32",
+#endif
+#ifdef SQLITE_NEED_ERR_NAME
+ "NEED_ERR_NAME",
+#endif
+#ifdef SQLITE_NO_SYNC
+ "NO_SYNC",
+#endif
+#ifdef SQLITE_OMIT_ALTERTABLE
+ "OMIT_ALTERTABLE",
+#endif
+#ifdef SQLITE_OMIT_ANALYZE
+ "OMIT_ANALYZE",
+#endif
+#ifdef SQLITE_OMIT_ATTACH
+ "OMIT_ATTACH",
+#endif
+#ifdef SQLITE_OMIT_AUTHORIZATION
+ "OMIT_AUTHORIZATION",
+#endif
+#ifdef SQLITE_OMIT_AUTOINCREMENT
+ "OMIT_AUTOINCREMENT",
+#endif
+#ifdef SQLITE_OMIT_AUTOINIT
+ "OMIT_AUTOINIT",
+#endif
+#ifdef SQLITE_OMIT_AUTOMATIC_INDEX
+ "OMIT_AUTOMATIC_INDEX",
+#endif
+#ifdef SQLITE_OMIT_AUTORESET
+ "OMIT_AUTORESET",
+#endif
+#ifdef SQLITE_OMIT_AUTOVACUUM
+ "OMIT_AUTOVACUUM",
+#endif
+#ifdef SQLITE_OMIT_BETWEEN_OPTIMIZATION
+ "OMIT_BETWEEN_OPTIMIZATION",
+#endif
+#ifdef SQLITE_OMIT_BLOB_LITERAL
+ "OMIT_BLOB_LITERAL",
+#endif
+#ifdef SQLITE_OMIT_CAST
+ "OMIT_CAST",
+#endif
+#ifdef SQLITE_OMIT_CHECK
+ "OMIT_CHECK",
+#endif
+#ifdef SQLITE_OMIT_COMPLETE
+ "OMIT_COMPLETE",
+#endif
+#ifdef SQLITE_OMIT_COMPOUND_SELECT
+ "OMIT_COMPOUND_SELECT",
+#endif
+#ifdef SQLITE_OMIT_CONFLICT_CLAUSE
+ "OMIT_CONFLICT_CLAUSE",
+#endif
+#ifdef SQLITE_OMIT_CTE
+ "OMIT_CTE",
+#endif
+#if defined(SQLITE_OMIT_DATETIME_FUNCS) || defined(SQLITE_OMIT_FLOATING_POINT)
+ "OMIT_DATETIME_FUNCS",
+#endif
+#ifdef SQLITE_OMIT_DECLTYPE
+ "OMIT_DECLTYPE",
+#endif
+#ifdef SQLITE_OMIT_DEPRECATED
+ "OMIT_DEPRECATED",
+#endif
+#ifdef SQLITE_OMIT_DESERIALIZE
+ "OMIT_DESERIALIZE",
+#endif
+#ifdef SQLITE_OMIT_DISKIO
+ "OMIT_DISKIO",
+#endif
+#ifdef SQLITE_OMIT_EXPLAIN
+ "OMIT_EXPLAIN",
+#endif
+#ifdef SQLITE_OMIT_FLAG_PRAGMAS
+ "OMIT_FLAG_PRAGMAS",
+#endif
+#ifdef SQLITE_OMIT_FLOATING_POINT
+ "OMIT_FLOATING_POINT",
+#endif
+#ifdef SQLITE_OMIT_FOREIGN_KEY
+ "OMIT_FOREIGN_KEY",
+#endif
+#ifdef SQLITE_OMIT_GET_TABLE
+ "OMIT_GET_TABLE",
+#endif
+#ifdef SQLITE_OMIT_HEX_INTEGER
+ "OMIT_HEX_INTEGER",
+#endif
+#ifdef SQLITE_OMIT_INCRBLOB
+ "OMIT_INCRBLOB",
+#endif
+#ifdef SQLITE_OMIT_INTEGRITY_CHECK
+ "OMIT_INTEGRITY_CHECK",
+#endif
+#ifdef SQLITE_OMIT_INTROSPECTION_PRAGMAS
+ "OMIT_INTROSPECTION_PRAGMAS",
+#endif
+#ifdef SQLITE_OMIT_JSON
+ "OMIT_JSON",
+#endif
+#ifdef SQLITE_OMIT_LIKE_OPTIMIZATION
+ "OMIT_LIKE_OPTIMIZATION",
+#endif
+#ifdef SQLITE_OMIT_LOAD_EXTENSION
+ "OMIT_LOAD_EXTENSION",
+#endif
+#ifdef SQLITE_OMIT_LOCALTIME
+ "OMIT_LOCALTIME",
+#endif
+#ifdef SQLITE_OMIT_LOOKASIDE
+ "OMIT_LOOKASIDE",
+#endif
+#ifdef SQLITE_OMIT_MEMORYDB
+ "OMIT_MEMORYDB",
+#endif
+#ifdef SQLITE_OMIT_OR_OPTIMIZATION
+ "OMIT_OR_OPTIMIZATION",
+#endif
+#ifdef SQLITE_OMIT_PAGER_PRAGMAS
+ "OMIT_PAGER_PRAGMAS",
+#endif
+#ifdef SQLITE_OMIT_PARSER_TRACE
+ "OMIT_PARSER_TRACE",
+#endif
+#ifdef SQLITE_OMIT_POPEN
+ "OMIT_POPEN",
+#endif
+#ifdef SQLITE_OMIT_PRAGMA
+ "OMIT_PRAGMA",
+#endif
+#ifdef SQLITE_OMIT_PROGRESS_CALLBACK
+ "OMIT_PROGRESS_CALLBACK",
+#endif
+#ifdef SQLITE_OMIT_QUICKBALANCE
+ "OMIT_QUICKBALANCE",
+#endif
+#ifdef SQLITE_OMIT_REINDEX
+ "OMIT_REINDEX",
+#endif
+#ifdef SQLITE_OMIT_SCHEMA_PRAGMAS
+ "OMIT_SCHEMA_PRAGMAS",
+#endif
+#ifdef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
+ "OMIT_SCHEMA_VERSION_PRAGMAS",
+#endif
+#ifdef SQLITE_OMIT_SHARED_CACHE
+ "OMIT_SHARED_CACHE",
+#endif
+#ifdef SQLITE_OMIT_SHUTDOWN_DIRECTORIES
+ "OMIT_SHUTDOWN_DIRECTORIES",
+#endif
+#ifdef SQLITE_OMIT_SUBQUERY
+ "OMIT_SUBQUERY",
+#endif
+#ifdef SQLITE_OMIT_TCL_VARIABLE
+ "OMIT_TCL_VARIABLE",
+#endif
+#ifdef SQLITE_OMIT_TEMPDB
+ "OMIT_TEMPDB",
+#endif
+#ifdef SQLITE_OMIT_TEST_CONTROL
+ "OMIT_TEST_CONTROL",
+#endif
+#ifdef SQLITE_OMIT_TRACE
+# if SQLITE_OMIT_TRACE != 1
+ "OMIT_TRACE=" CTIMEOPT_VAL(SQLITE_OMIT_TRACE),
+# endif
+#endif
+#ifdef SQLITE_OMIT_TRIGGER
+ "OMIT_TRIGGER",
+#endif
+#ifdef SQLITE_OMIT_TRUNCATE_OPTIMIZATION
+ "OMIT_TRUNCATE_OPTIMIZATION",
+#endif
+#ifdef SQLITE_OMIT_UTF16
+ "OMIT_UTF16",
+#endif
+#ifdef SQLITE_OMIT_VACUUM
+ "OMIT_VACUUM",
+#endif
+#ifdef SQLITE_OMIT_VIEW
+ "OMIT_VIEW",
+#endif
+#ifdef SQLITE_OMIT_VIRTUALTABLE
+ "OMIT_VIRTUALTABLE",
+#endif
+#ifdef SQLITE_OMIT_WAL
+ "OMIT_WAL",
+#endif
+#ifdef SQLITE_OMIT_WSD
+ "OMIT_WSD",
+#endif
+#ifdef SQLITE_OMIT_XFER_OPT
+ "OMIT_XFER_OPT",
+#endif
+#ifdef SQLITE_PCACHE_SEPARATE_HEADER
+ "PCACHE_SEPARATE_HEADER",
+#endif
+#ifdef SQLITE_PERFORMANCE_TRACE
+ "PERFORMANCE_TRACE",
+#endif
+#ifdef SQLITE_POWERSAFE_OVERWRITE
+# if SQLITE_POWERSAFE_OVERWRITE != 1
+ "POWERSAFE_OVERWRITE=" CTIMEOPT_VAL(SQLITE_POWERSAFE_OVERWRITE),
+# endif
+#endif
+#ifdef SQLITE_PREFER_PROXY_LOCKING
+ "PREFER_PROXY_LOCKING",
+#endif
+#ifdef SQLITE_PROXY_DEBUG
+ "PROXY_DEBUG",
+#endif
+#ifdef SQLITE_REVERSE_UNORDERED_SELECTS
+ "REVERSE_UNORDERED_SELECTS",
+#endif
+#ifdef SQLITE_RTREE_INT_ONLY
+ "RTREE_INT_ONLY",
+#endif
+#ifdef SQLITE_SECURE_DELETE
+ "SECURE_DELETE",
+#endif
+#ifdef SQLITE_SMALL_STACK
+ "SMALL_STACK",
+#endif
+#ifdef SQLITE_SORTER_PMASZ
+ "SORTER_PMASZ=" CTIMEOPT_VAL(SQLITE_SORTER_PMASZ),
+#endif
+#ifdef SQLITE_SOUNDEX
+ "SOUNDEX",
+#endif
+#ifdef SQLITE_STAT4_SAMPLES
+ "STAT4_SAMPLES=" CTIMEOPT_VAL(SQLITE_STAT4_SAMPLES),
+#endif
+#ifdef SQLITE_STMTJRNL_SPILL
+ "STMTJRNL_SPILL=" CTIMEOPT_VAL(SQLITE_STMTJRNL_SPILL),
+#endif
+#ifdef SQLITE_SUBSTR_COMPATIBILITY
+ "SUBSTR_COMPATIBILITY",
+#endif
+#if (!defined(SQLITE_WIN32_MALLOC) \
+ && !defined(SQLITE_ZERO_MALLOC) \
+ && !defined(SQLITE_MEMDEBUG) \
+ ) || defined(SQLITE_SYSTEM_MALLOC)
+ "SYSTEM_MALLOC",
+#endif
+#ifdef SQLITE_TCL
+ "TCL",
+#endif
+#ifdef SQLITE_TEMP_STORE
+ "TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE),
+#endif
+#ifdef SQLITE_TEST
+ "TEST",
+#endif
+#if defined(SQLITE_THREADSAFE)
+ "THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE),
+#elif defined(THREADSAFE)
+ "THREADSAFE=" CTIMEOPT_VAL(THREADSAFE),
#else
- return "unknown";
+ "THREADSAFE=1",
+#endif
+#ifdef SQLITE_UNLINK_AFTER_CLOSE
+ "UNLINK_AFTER_CLOSE",
+#endif
+#ifdef SQLITE_UNTESTABLE
+ "UNTESTABLE",
+#endif
+#ifdef SQLITE_USER_AUTHENTICATION
+ "USER_AUTHENTICATION",
+#endif
+#ifdef SQLITE_USE_ALLOCA
+ "USE_ALLOCA",
+#endif
+#ifdef SQLITE_USE_FCNTL_TRACE
+ "USE_FCNTL_TRACE",
+#endif
+#ifdef SQLITE_USE_URI
+ "USE_URI",
+#endif
+#ifdef SQLITE_VDBE_COVERAGE
+ "VDBE_COVERAGE",
+#endif
+#ifdef SQLITE_WIN32_MALLOC
+ "WIN32_MALLOC",
+#endif
+#ifdef SQLITE_ZERO_MALLOC
+ "ZERO_MALLOC",
#endif
-}
-
-static int sqlcipher_cc_hmac(void *ctx, int algorithm, unsigned char *hmac_key, int key_sz, unsigned char *in, int in_sz, unsigned char *in2, int in2_sz, unsigned char *out) {
- CCHmacContext hmac_context;
- if(in == NULL) return SQLITE_ERROR;
- switch(algorithm) {
- case SQLCIPHER_HMAC_SHA1:
- CCHmacInit(&hmac_context, kCCHmacAlgSHA1, hmac_key, key_sz);
- break;
- case SQLCIPHER_HMAC_SHA256:
- CCHmacInit(&hmac_context, kCCHmacAlgSHA256, hmac_key, key_sz);
- break;
- case SQLCIPHER_HMAC_SHA512:
- CCHmacInit(&hmac_context, kCCHmacAlgSHA512, hmac_key, key_sz);
- break;
- default:
- return SQLITE_ERROR;
- }
- CCHmacUpdate(&hmac_context, in, in_sz);
- if(in2 != NULL) CCHmacUpdate(&hmac_context, in2, in2_sz);
- CCHmacFinal(&hmac_context, out);
- return SQLITE_OK;
-}
-
-static int sqlcipher_cc_kdf(void *ctx, int algorithm, const unsigned char *pass, int pass_sz, unsigned char* salt, int salt_sz, int workfactor, int key_sz, unsigned char *key) {
- switch(algorithm) {
- case SQLCIPHER_HMAC_SHA1:
- if(CCKeyDerivationPBKDF(kCCPBKDF2, (const char *)pass, pass_sz, salt, salt_sz, kCCPRFHmacAlgSHA1, workfactor, key, key_sz) != kCCSuccess) return SQLITE_ERROR;
- break;
- case SQLCIPHER_HMAC_SHA256:
- if(CCKeyDerivationPBKDF(kCCPBKDF2, (const char *)pass, pass_sz, salt, salt_sz, kCCPRFHmacAlgSHA256, workfactor, key, key_sz) != kCCSuccess) return SQLITE_ERROR;
- break;
- case SQLCIPHER_HMAC_SHA512:
- if(CCKeyDerivationPBKDF(kCCPBKDF2, (const char *)pass, pass_sz, salt, salt_sz, kCCPRFHmacAlgSHA512, workfactor, key, key_sz) != kCCSuccess) return SQLITE_ERROR;
- break;
- default:
- return SQLITE_ERROR;
- }
- return SQLITE_OK;
-}
-
-static int sqlcipher_cc_cipher(void *ctx, int mode, unsigned char *key, int key_sz, unsigned char *iv, unsigned char *in, int in_sz, unsigned char *out) {
- CCCryptorRef cryptor;
- size_t tmp_csz, csz;
- CCOperation op = mode == CIPHER_ENCRYPT ? kCCEncrypt : kCCDecrypt;
-
- if(CCCryptorCreate(op, kCCAlgorithmAES128, 0, key, kCCKeySizeAES256, iv, &cryptor) != kCCSuccess) return SQLITE_ERROR;
- if(CCCryptorUpdate(cryptor, in, in_sz, out, in_sz, &tmp_csz) != kCCSuccess) return SQLITE_ERROR;
- csz = tmp_csz;
- out += tmp_csz;
- if(CCCryptorFinal(cryptor, out, in_sz - csz, &tmp_csz) != kCCSuccess) return SQLITE_ERROR;
- csz += tmp_csz;
- if(CCCryptorRelease(cryptor) != kCCSuccess) return SQLITE_ERROR;
- assert(in_sz == csz);
-
- return SQLITE_OK;
-}
-
-static const char* sqlcipher_cc_get_cipher(void *ctx) {
- return "aes-256-cbc";
-}
-
-static int sqlcipher_cc_get_key_sz(void *ctx) {
- return kCCKeySizeAES256;
-}
-
-static int sqlcipher_cc_get_iv_sz(void *ctx) {
- return kCCBlockSizeAES128;
-}
-
-static int sqlcipher_cc_get_block_sz(void *ctx) {
- return kCCBlockSizeAES128;
-}
-
-static int sqlcipher_cc_get_hmac_sz(void *ctx, int algorithm) {
- switch(algorithm) {
- case SQLCIPHER_HMAC_SHA1:
- return CC_SHA1_DIGEST_LENGTH;
- break;
- case SQLCIPHER_HMAC_SHA256:
- return CC_SHA256_DIGEST_LENGTH;
- break;
- case SQLCIPHER_HMAC_SHA512:
- return CC_SHA512_DIGEST_LENGTH;
- break;
- default:
- return 0;
- }
-}
-
-static int sqlcipher_cc_ctx_init(void **ctx) {
- return SQLITE_OK;
-}
-
-static int sqlcipher_cc_ctx_free(void **ctx) {
- return SQLITE_OK;
-}
-static int sqlcipher_cc_fips_status(void *ctx) {
- return 0;
-}
+} ;
-int sqlcipher_cc_setup(sqlcipher_provider *p) {
- p->random = sqlcipher_cc_random;
- p->get_provider_name = sqlcipher_cc_get_provider_name;
- p->hmac = sqlcipher_cc_hmac;
- p->kdf = sqlcipher_cc_kdf;
- p->cipher = sqlcipher_cc_cipher;
- p->get_cipher = sqlcipher_cc_get_cipher;
- p->get_key_sz = sqlcipher_cc_get_key_sz;
- p->get_iv_sz = sqlcipher_cc_get_iv_sz;
- p->get_block_sz = sqlcipher_cc_get_block_sz;
- p->get_hmac_sz = sqlcipher_cc_get_hmac_sz;
- p->ctx_init = sqlcipher_cc_ctx_init;
- p->ctx_free = sqlcipher_cc_ctx_free;
- p->add_random = sqlcipher_cc_add_random;
- p->fips_status = sqlcipher_cc_fips_status;
- p->get_provider_version = sqlcipher_cc_get_provider_version;
- return SQLITE_OK;
+SQLITE_PRIVATE const char **sqlcipher_sqlite3CompileOptions(int *pnOpt){
+ *pnOpt = sizeof(sqlcipher_sqlite3azCompileOpt) / sizeof(sqlcipher_sqlite3azCompileOpt[0]);
+ return (const char**)sqlcipher_sqlite3azCompileOpt;
}
-#endif
-#endif
-/* END SQLCIPHER */
+#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
-/************** End of crypto_cc.c *******************************************/
+/************** End of ctime.c ***********************************************/
/************** Begin file global.c ******************************************/
/*
** 2008 June 13
@@ -25645,7 +21871,7 @@ SQLITE_PRIVATE const unsigned char sqlcipher_sqlite3UpperToLower[] = {
198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,
216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,
234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,
- 252,253,254,255
+ 252,253,254,255,
#endif
#ifdef SQLITE_EBCDIC
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 0x */
@@ -25665,7 +21891,35 @@ SQLITE_PRIVATE const unsigned char sqlcipher_sqlite3UpperToLower[] = {
224,225,162,163,164,165,166,167,168,169,234,235,236,237,238,239, /* Ex */
240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255, /* Fx */
#endif
+/* All of the upper-to-lower conversion data is above. The following
+** 18 integers are completely unrelated. They are appended to the
+** sqlcipher_sqlite3UpperToLower[] array to avoid UBSAN warnings. Here's what is
+** going on:
+**
+** The SQL comparison operators (<>, =, >, <=, <, and >=) are implemented
+** by invoking sqlcipher_sqlite3MemCompare(A,B) which compares values A and B and
+** returns negative, zero, or positive if A is less then, equal to, or
+** greater than B, respectively. Then the true false results is found by
+** consulting sqlcipher_sqlite3aLTb[opcode], sqlcipher_sqlite3aEQb[opcode], or
+** sqlcipher_sqlite3aGTb[opcode] depending on whether the result of compare(A,B)
+** is negative, zero, or positive, where opcode is the specific opcode.
+** The only works because the comparison opcodes are consecutive and in
+** this order: NE EQ GT LE LT GE. Various assert()s throughout the code
+** ensure that is the case.
+**
+** These elements must be appended to another array. Otherwise the
+** index (here shown as [256-OP_Ne]) would be out-of-bounds and thus
+** be undefined behavior. That's goofy, but the C-standards people thought
+** it was a good idea, so here we are.
+*/
+/* NE EQ GT LE LT GE */
+ 1, 0, 0, 1, 1, 0, /* aLTb[]: Use when compare(A,B) less than zero */
+ 0, 1, 0, 1, 0, 1, /* aEQb[]: Use when compare(A,B) equals zero */
+ 1, 0, 1, 0, 0, 1 /* aGTb[]: Use when compare(A,B) greater than zero*/
};
+SQLITE_PRIVATE const unsigned char *sqlcipher_sqlite3aLTb = &sqlcipher_sqlite3UpperToLower[256-OP_Ne];
+SQLITE_PRIVATE const unsigned char *sqlcipher_sqlite3aEQb = &sqlcipher_sqlite3UpperToLower[256+6-OP_Ne];
+SQLITE_PRIVATE const unsigned char *sqlcipher_sqlite3aGTb = &sqlcipher_sqlite3UpperToLower[256+12-OP_Ne];
/*
** The following 256 byte lookup table is used to support SQLites built-in
@@ -25868,16 +22122,20 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlcipher_sqlite3Config = {
0, /* xVdbeBranch */
0, /* pVbeBranchArg */
#endif
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
SQLITE_MEMDB_DEFAULT_MAXSIZE, /* mxMemdbSize */
#endif
#ifndef SQLITE_UNTESTABLE
0, /* xTestCallback */
#endif
0, /* bLocaltimeFault */
+ 0, /* xAltLocaltime */
0x7ffffffe, /* iOnceResetThreshold */
SQLITE_DEFAULT_SORTERREF_SIZE, /* szSorterRef */
0, /* iPrngSeed */
+#ifdef SQLITE_DEBUG
+ {0,0,0,0,0,0} /* aTune */
+#endif
};
/*
@@ -25887,6 +22145,18 @@ SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlcipher_sqlite3Config = {
*/
SQLITE_PRIVATE FuncDefHash sqlcipher_sqlite3BuiltinFunctions;
+#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_DEBUG)
+/*
+** Counter used for coverage testing. Does not come into play for
+** release builds.
+**
+** Access to this global variable is not mutex protected. This might
+** result in TSAN warnings. But as the variable does not exist in
+** release builds, that should not be a concern.
+*/
+SQLITE_PRIVATE unsigned int sqlcipher_sqlite3CoverageCounter;
+#endif /* SQLITE_COVERAGE_TEST || SQLITE_DEBUG */
+
#ifdef VDBE_PROFILE
/*
** The following performance counter can be used in place of
@@ -25918,9 +22188,10 @@ SQLITE_PRIVATE int sqlcipher_sqlite3PendingByte = 0x40000000;
#endif
/*
-** Flags for select tracing and the ".selecttrace" macro of the CLI
+** Tracing flags set by SQLITE_TESTCTRL_TRACEFLAGS.
*/
-SQLITE_API u32 sqlcipher_sqlite3_unsupported_selecttrace = 0;
+SQLITE_PRIVATE u32 sqlcipher_sqlite3TreeTrace = 0;
+SQLITE_PRIVATE u32 sqlcipher_sqlite3WhereTrace = 0;
/* #include "opcodes.h" */
/*
@@ -25936,6 +22207,48 @@ SQLITE_PRIVATE const unsigned char sqlcipher_sqlite3OpcodeProperty[] = OPFLG_INI
*/
SQLITE_PRIVATE const char sqlcipher_sqlite3StrBINARY[] = "BINARY";
+/*
+** Standard typenames. These names must match the COLTYPE_* definitions.
+** Adjust the SQLITE_N_STDTYPE value if adding or removing entries.
+**
+** sqlcipher_sqlite3StdType[] The actual names of the datatypes.
+**
+** sqlcipher_sqlite3StdTypeLen[] The length (in bytes) of each entry
+** in sqlcipher_sqlite3StdType[].
+**
+** sqlcipher_sqlite3StdTypeAffinity[] The affinity associated with each entry
+** in sqlcipher_sqlite3StdType[].
+**
+** sqlcipher_sqlite3StdTypeMap[] The type value (as returned from
+** sqlcipher_sqlite3_column_type() or sqlcipher_sqlite3_value_type())
+** for each entry in sqlcipher_sqlite3StdType[].
+*/
+SQLITE_PRIVATE const unsigned char sqlcipher_sqlite3StdTypeLen[] = { 3, 4, 3, 7, 4, 4 };
+SQLITE_PRIVATE const char sqlcipher_sqlite3StdTypeAffinity[] = {
+ SQLITE_AFF_NUMERIC,
+ SQLITE_AFF_BLOB,
+ SQLITE_AFF_INTEGER,
+ SQLITE_AFF_INTEGER,
+ SQLITE_AFF_REAL,
+ SQLITE_AFF_TEXT
+};
+SQLITE_PRIVATE const char sqlcipher_sqlite3StdTypeMap[] = {
+ 0,
+ SQLITE_BLOB,
+ SQLITE_INTEGER,
+ SQLITE_INTEGER,
+ SQLITE_FLOAT,
+ SQLITE_TEXT
+};
+SQLITE_PRIVATE const char *sqlcipher_sqlite3StdType[] = {
+ "ANY",
+ "BLOB",
+ "INT",
+ "INTEGER",
+ "REAL",
+ "TEXT"
+};
+
/************** End of global.c **********************************************/
/************** Begin file status.c ******************************************/
/*
@@ -26033,7 +22346,7 @@ typedef struct AuxData AuxData;
typedef struct VdbeCursor VdbeCursor;
struct VdbeCursor {
u8 eCurType; /* One of the CURTYPE_* values above */
- i8 iDb; /* Index of cursor database in db->aDb[] (or -1) */
+ i8 iDb; /* Index of cursor database in db->aDb[] */
u8 nullRow; /* True if pointing to a row with no data */
u8 deferredMoveto; /* A call to sqlcipher_sqlite3BtreeMoveto() is needed */
u8 isTable; /* True for rowid tables. False for indexes */
@@ -26044,10 +22357,13 @@ struct VdbeCursor {
Bool isEphemeral:1; /* True for an ephemeral table */
Bool useRandomRowid:1; /* Generate new record numbers semi-randomly */
Bool isOrdered:1; /* True if the table is not BTREE_UNORDERED */
+ Bool noReuse:1; /* OpenEphemeral may not reuse this cursor */
u16 seekHit; /* See the OP_SeekHit and OP_IfNoHope opcodes */
- Btree *pBtx; /* Separate file holding temporary table */
+ union { /* pBtx for isEphermeral. pAltMap otherwise */
+ Btree *pBtx; /* Separate file holding temporary table */
+ u32 *aAltMap; /* Mapping from table to index column numbers */
+ } ub;
i64 seqCount; /* Sequence counter */
- u32 *aAltMap; /* Mapping from table to index column numbers */
/* Cached OP_Column parse information is only valid if cacheStatus matches
** Vdbe.cacheCtr. Vdbe.cacheCtr will never take on the value of
@@ -26089,6 +22405,11 @@ struct VdbeCursor {
u32 aType[1]; /* Type values record decode. MUST BE LAST */
};
+/* Return true if P is a null-only cursor
+*/
+#define IsNullCursor(P) \
+ ((P)->eCurType==CURTYPE_PSEUDO && (P)->nullRow && (P)->seekResult==0)
+
/*
** A value for VdbeCursor.cacheStatus that means the cache is always invalid.
@@ -26137,8 +22458,8 @@ struct VdbeFrame {
int nMem; /* Number of entries in aMem */
int nChildMem; /* Number of memory cells for child frame */
int nChildCsr; /* Number of cursors for child frame */
- int nChange; /* Statement changes (Vdbe.nChange) */
- int nDbChange; /* Value of db->nChange */
+ i64 nChange; /* Statement changes (Vdbe.nChange) */
+ i64 nDbChange; /* Value of db->nChange */
};
/* Magic number for sanity checking on VdbeFrame objects */
@@ -26163,16 +22484,16 @@ struct sqlcipher_sqlite3_value {
const char *zPType; /* Pointer type when MEM_Term|MEM_Subtype|MEM_Null */
FuncDef *pDef; /* Used only when flags==MEM_Agg */
} u;
+ char *z; /* String or BLOB value */
+ int n; /* Number of characters in string value, excluding '\0' */
u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */
u8 enc; /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */
u8 eSubtype; /* Subtype for this value */
- int n; /* Number of characters in string value, excluding '\0' */
- char *z; /* String or BLOB value */
/* ShallowCopy only needs to copy the information above */
- char *zMalloc; /* Space to hold MEM_Str or MEM_Blob if szMalloc>0 */
+ sqlcipher_sqlite3 *db; /* The associated database connection */
int szMalloc; /* Size of the zMalloc allocation */
u32 uTemp; /* Transient storage for serial_type in OP_MakeRecord */
- sqlcipher_sqlite3 *db; /* The associated database connection */
+ char *zMalloc; /* Space to hold MEM_Str or MEM_Blob if szMalloc>0 */
void (*xDel)(void*);/* Destructor for Mem.z - only valid if MEM_Dyn */
#ifdef SQLITE_DEBUG
Mem *pScopyFrom; /* This Mem is a shallow copy of pScopyFrom */
@@ -26184,11 +22505,43 @@ struct sqlcipher_sqlite3_value {
** Size of struct Mem not including the Mem.zMalloc member or anything that
** follows.
*/
-#define MEMCELLSIZE offsetof(Mem,zMalloc)
+#define MEMCELLSIZE offsetof(Mem,db)
-/* One or more of the following flags are set to indicate the validOK
+/* One or more of the following flags are set to indicate the
** representations of the value stored in the Mem struct.
**
+** * MEM_Null An SQL NULL value
+**
+** * MEM_Null|MEM_Zero An SQL NULL with the virtual table
+** UPDATE no-change flag set
+**
+** * MEM_Null|MEM_Term| An SQL NULL, but also contains a
+** MEM_Subtype pointer accessible using
+** sqlcipher_sqlite3_value_pointer().
+**
+** * MEM_Null|MEM_Cleared Special SQL NULL that compares non-equal
+** to other NULLs even using the IS operator.
+**
+** * MEM_Str A string, stored in Mem.z with
+** length Mem.n. Zero-terminated if
+** MEM_Term is set. This flag is
+** incompatible with MEM_Blob and
+** MEM_Null, but can appear with MEM_Int,
+** MEM_Real, and MEM_IntReal.
+**
+** * MEM_Blob A blob, stored in Mem.z length Mem.n.
+** Incompatible with MEM_Str, MEM_Null,
+** MEM_Int, MEM_Real, and MEM_IntReal.
+**
+** * MEM_Blob|MEM_Zero A blob in Mem.z of length Mem.n plus
+** MEM.u.i extra 0x00 bytes at the end.
+**
+** * MEM_Int Integer stored in Mem.u.i.
+**
+** * MEM_Real Real stored in Mem.u.r.
+**
+** * MEM_IntReal Real stored as an integer in Mem.u.i.
+**
** If the MEM_Null flag is set, then the value is an SQL NULL value.
** For a pointer type created using sqlcipher_sqlite3_bind_pointer() or
** sqlcipher_sqlite3_result_pointer() the MEM_Term and MEM_Subtype flags are also set.
@@ -26199,6 +22552,7 @@ struct sqlcipher_sqlite3_value {
** set, then the string is nul terminated. The MEM_Int and MEM_Real
** flags may coexist with the MEM_Str flag.
*/
+#define MEM_Undefined 0x0000 /* Value is undefined */
#define MEM_Null 0x0001 /* Value is NULL (or a pointer) */
#define MEM_Str 0x0002 /* Value is a string */
#define MEM_Int 0x0004 /* Value is an integer */
@@ -26206,28 +22560,24 @@ struct sqlcipher_sqlite3_value {
#define MEM_Blob 0x0010 /* Value is a BLOB */
#define MEM_IntReal 0x0020 /* MEM_Int that stringifies like MEM_Real */
#define MEM_AffMask 0x003f /* Mask of affinity bits */
+
+/* Extra bits that modify the meanings of the core datatypes above
+*/
#define MEM_FromBind 0x0040 /* Value originates from sqlcipher_sqlite3_bind() */
-#define MEM_Undefined 0x0080 /* Value is undefined */
+ /* 0x0080 // Available */
#define MEM_Cleared 0x0100 /* NULL set by OP_Null, not from data */
-#define MEM_TypeMask 0xc1bf /* Mask of type bits */
-
+#define MEM_Term 0x0200 /* String in Mem.z is zero terminated */
+#define MEM_Zero 0x0400 /* Mem.i contains count of 0s appended to blob */
+#define MEM_Subtype 0x0800 /* Mem.eSubtype is valid */
+#define MEM_TypeMask 0x0dbf /* Mask of type bits */
-/* Whenever Mem contains a valid string or blob representation, one of
-** the following flags must be set to determine the memory management
-** policy for Mem.z. The MEM_Term flag tells us whether or not the
-** string is \000 or \u0000 terminated
+/* Bits that determine the storage for Mem.z for a string or blob or
+** aggregate accumulator.
*/
-#define MEM_Term 0x0200 /* String in Mem.z is zero terminated */
-#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 */
-#define MEM_Zero 0x4000 /* Mem.i contains count of 0s appended to blob */
-#define MEM_Subtype 0x8000 /* Mem.eSubtype is valid */
-#ifdef SQLITE_OMIT_INCRBLOB
- #undef MEM_Zero
- #define MEM_Zero 0x0000
-#endif
+#define MEM_Dyn 0x1000 /* Need to call Mem.xDel() on Mem.z */
+#define MEM_Static 0x2000 /* Mem.z points to a static string */
+#define MEM_Ephem 0x4000 /* Mem.z points to an ephemeral string */
+#define MEM_Agg 0x8000 /* Mem.z points to an agg function context */
/* Return TRUE if Mem X contains dynamically allocated content - anything
** that needs to be deallocated to avoid a leak.
@@ -26249,11 +22599,15 @@ struct sqlcipher_sqlite3_value {
&& (X)->n==0 && (X)->u.nZero==0)
/*
-** Return true if a memory cell is not marked as invalid. This macro
+** Return true if a memory cell has been initialized and is valid.
** is for use inside assert() statements only.
+**
+** A Memory cell is initialized if at least one of the
+** MEM_Null, MEM_Str, MEM_Int, MEM_Real, MEM_Blob, or MEM_IntReal bits
+** is set. It is "undefined" if all those bits are zero.
*/
#ifdef SQLITE_DEBUG
-#define memIsValid(M) ((M)->flags & MEM_Undefined)==0
+#define memIsValid(M) ((M)->flags & MEM_AffMask)!=0
#endif
/*
@@ -26291,6 +22645,7 @@ struct sqlcipher_sqlite3_context {
Vdbe *pVdbe; /* The VM that owns this context */
int iOp; /* Instruction number of OP_Function */
int isError; /* Error code returned by the function. */
+ u8 enc; /* Encoding to use for results */
u8 skipFlag; /* Skip accumulator loading if true */
u8 argc; /* Number of arguments */
sqlcipher_sqlite3_value *argv[1]; /* Argument set */
@@ -26339,13 +22694,12 @@ struct Vdbe {
Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */
Parse *pParse; /* Parsing context used to create this Vdbe */
ynVar nVar; /* Number of entries in aVar[] */
- u32 magic; /* Magic number for sanity checking */
int nMem; /* Number of memory locations currently allocated */
int nCursor; /* Number of slots in apCsr[] */
u32 cacheCtr; /* VdbeCursor row cache generation counter */
int pc; /* The program counter */
int rc; /* Value to return */
- int nChange; /* Number of db changes made since last reset */
+ i64 nChange; /* Number of db changes made since last reset */
int iStatement; /* Statement number (or 0 if has no opened stmt) */
i64 iCurrentTime; /* Value of julianday('now') for this statement */
i64 nFkConstraint; /* Number of imm. FK constraints this VM */
@@ -26377,17 +22731,16 @@ struct Vdbe {
u8 errorAction; /* Recovery action to do in case of an error */
u8 minWriteFileFormat; /* Minimum file format for writable database files */
u8 prepFlags; /* SQLITE_PREPARE_* flags */
- u8 doingRerun; /* True if rerunning after an auto-reprepare */
+ u8 eVdbeState; /* On of the VDBE_*_STATE values */
bft expired:2; /* 1: recompile VM immediately 2: when convenient */
bft explain:2; /* True if EXPLAIN present on SQL command */
bft changeCntOn:1; /* True to update the change-counter */
- bft runOnlyOnce:1; /* Automatically expire on reset */
bft usesStmtJournal:1; /* True if uses a statement journal */
bft readOnly:1; /* True for statements that do not write */
bft bIsReader:1; /* True for statements that read */
yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */
yDbMask lockMask; /* Subset of btreeMask that requires a lock */
- u32 aCounter[7]; /* Counters used by sqlcipher_sqlite3_stmt_status() */
+ u32 aCounter[9]; /* Counters used by sqlcipher_sqlite3_stmt_status() */
char *zSql; /* Text of the SQL statement that generated this */
#ifdef SQLITE_ENABLE_NORMALIZE
char *zNormSql; /* Normalization of the associated SQL statement */
@@ -26408,13 +22761,12 @@ struct Vdbe {
};
/*
-** The following are allowed values for Vdbe.magic
+** The following are allowed values for Vdbe.eVdbeState
*/
-#define VDBE_MAGIC_INIT 0x16bceaa5 /* Building a VDBE program */
-#define VDBE_MAGIC_RUN 0x2df20da3 /* VDBE is ready to execute */
-#define VDBE_MAGIC_HALT 0x319c2973 /* VDBE has completed execution */
-#define VDBE_MAGIC_RESET 0x48fa9f76 /* Reset and ready to run again */
-#define VDBE_MAGIC_DEAD 0x5606c3c8 /* The VDBE has been deallocated */
+#define VDBE_INIT_STATE 0 /* Prepared statement under construction */
+#define VDBE_READY_STATE 1 /* Ready to run but not yet started */
+#define VDBE_RUN_STATE 2 /* Run in progress */
+#define VDBE_HALT_STATE 3 /* Finished. Need reset() or finalize() */
/*
** Structure used to store the context required by the
@@ -26429,6 +22781,7 @@ struct PreUpdate {
UnpackedRecord *pUnpacked; /* Unpacked version of aRecord[] */
UnpackedRecord *pNewUnpacked; /* Unpacked version of new.* record */
int iNewReg; /* Register for new.* values */
+ int iBlobWrite; /* Value returned by preupdate_blobwrite() */
i64 iKey1; /* First key value passed to hook */
i64 iKey2; /* Second key value passed to hook */
Mem *aNew; /* Array of new.* values */
@@ -26437,18 +22790,49 @@ struct PreUpdate {
};
/*
+** An instance of this object is used to pass an vector of values into
+** OP_VFilter, the xFilter method of a virtual table. The vector is the
+** set of values on the right-hand side of an IN constraint.
+**
+** The value as passed into xFilter is an sqlcipher_sqlite3_value with a "pointer"
+** type, such as is generated by sqlcipher_sqlite3_result_pointer() and read by
+** sqlcipher_sqlite3_value_pointer. Such values have MEM_Term|MEM_Subtype|MEM_Null
+** and a subtype of 'p'. The sqlcipher_sqlite3_vtab_in_first() and _next() interfaces
+** know how to use this object to step through all the values in the
+** right operand of the IN constraint.
+*/
+typedef struct ValueList ValueList;
+struct ValueList {
+ BtCursor *pCsr; /* An ephemeral table holding all values */
+ sqlcipher_sqlite3_value *pOut; /* Register to hold each decoded output value */
+};
+
+/* Size of content associated with serial types that fit into a
+** single-byte varint.
+*/
+#ifndef SQLITE_AMALGAMATION
+SQLITE_PRIVATE const u8 sqlcipher_sqlite3SmallTypeSizes[];
+#endif
+
+/*
** Function prototypes
*/
SQLITE_PRIVATE void sqlcipher_sqlite3VdbeError(Vdbe*, const char *, ...);
SQLITE_PRIVATE void sqlcipher_sqlite3VdbeFreeCursor(Vdbe *, VdbeCursor*);
+SQLITE_PRIVATE void sqlcipher_sqlite3VdbeFreeCursorNN(Vdbe*,VdbeCursor*);
void sqliteVdbePopStack(Vdbe*,int);
+SQLITE_PRIVATE int SQLITE_NOINLINE sqlcipher_sqlite3VdbeHandleMovedCursor(VdbeCursor *p);
SQLITE_PRIVATE int SQLITE_NOINLINE sqlcipher_sqlite3VdbeFinishMoveto(VdbeCursor*);
-SQLITE_PRIVATE int sqlcipher_sqlite3VdbeCursorMoveto(VdbeCursor**, u32*);
SQLITE_PRIVATE int sqlcipher_sqlite3VdbeCursorRestore(VdbeCursor*);
SQLITE_PRIVATE u32 sqlcipher_sqlite3VdbeSerialTypeLen(u32);
SQLITE_PRIVATE u8 sqlcipher_sqlite3VdbeOneByteSerialTypeLen(u8);
-SQLITE_PRIVATE u32 sqlcipher_sqlite3VdbeSerialPut(unsigned char*, Mem*, u32);
-SQLITE_PRIVATE u32 sqlcipher_sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
+#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT
+SQLITE_PRIVATE u64 sqlcipher_sqlite3FloatSwap(u64 in);
+# define swapMixedEndianFloat(X) X = sqlcipher_sqlite3FloatSwap(X)
+#else
+# define swapMixedEndianFloat(X)
+#endif
+SQLITE_PRIVATE void sqlcipher_sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
SQLITE_PRIVATE void sqlcipher_sqlite3VdbeDeleteAuxData(sqlcipher_sqlite3*, AuxData**, int, int);
int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
@@ -26472,7 +22856,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VdbeMemCopy(Mem*, const Mem*);
SQLITE_PRIVATE void sqlcipher_sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int);
SQLITE_PRIVATE void sqlcipher_sqlite3VdbeMemMove(Mem*, Mem*);
SQLITE_PRIVATE int sqlcipher_sqlite3VdbeMemNulTerminate(Mem*);
-SQLITE_PRIVATE int sqlcipher_sqlite3VdbeMemSetStr(Mem*, const char*, int, u8, void(*)(void*));
+SQLITE_PRIVATE int sqlcipher_sqlite3VdbeMemSetStr(Mem*, const char*, i64, u8, void(*)(void*));
SQLITE_PRIVATE void sqlcipher_sqlite3VdbeMemSetInt64(Mem*, i64);
#ifdef SQLITE_OMIT_FLOATING_POINT
# define sqlcipher_sqlite3VdbeMemSetDouble sqlcipher_sqlite3VdbeMemSetInt64
@@ -26482,14 +22866,19 @@ SQLITE_PRIVATE void sqlcipher_sqlite3VdbeMemSetDouble(Mem*, double);
SQLITE_PRIVATE void sqlcipher_sqlite3VdbeMemSetPointer(Mem*, void*, const char*, void(*)(void*));
SQLITE_PRIVATE void sqlcipher_sqlite3VdbeMemInit(Mem*,sqlcipher_sqlite3*,u16);
SQLITE_PRIVATE void sqlcipher_sqlite3VdbeMemSetNull(Mem*);
+#ifndef SQLITE_OMIT_INCRBLOB
SQLITE_PRIVATE void sqlcipher_sqlite3VdbeMemSetZeroBlob(Mem*,int);
+#else
+SQLITE_PRIVATE int sqlcipher_sqlite3VdbeMemSetZeroBlob(Mem*,int);
+#endif
#ifdef SQLITE_DEBUG
SQLITE_PRIVATE int sqlcipher_sqlite3VdbeMemIsRowSet(const Mem*);
#endif
SQLITE_PRIVATE int sqlcipher_sqlite3VdbeMemSetRowSet(Mem*);
SQLITE_PRIVATE int sqlcipher_sqlite3VdbeMemMakeWriteable(Mem*);
SQLITE_PRIVATE int sqlcipher_sqlite3VdbeMemStringify(Mem*, u8, u8);
-SQLITE_PRIVATE i64 sqlcipher_sqlite3VdbeIntValue(Mem*);
+SQLITE_PRIVATE int sqlcipher_sqlite3IntFloatCompare(i64,double);
+SQLITE_PRIVATE i64 sqlcipher_sqlite3VdbeIntValue(const Mem*);
SQLITE_PRIVATE int sqlcipher_sqlite3VdbeMemIntegerify(Mem*);
SQLITE_PRIVATE double sqlcipher_sqlite3VdbeRealValue(Mem*);
SQLITE_PRIVATE int sqlcipher_sqlite3VdbeBooleanValue(Mem*, int ifNull);
@@ -26500,6 +22889,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VdbeMemCast(Mem*,u8,u8);
SQLITE_PRIVATE int sqlcipher_sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,Mem*);
SQLITE_PRIVATE int sqlcipher_sqlite3VdbeMemFromBtreeZeroOffset(BtCursor*,u32,Mem*);
SQLITE_PRIVATE void sqlcipher_sqlite3VdbeMemRelease(Mem *p);
+SQLITE_PRIVATE void sqlcipher_sqlite3VdbeMemReleaseMalloc(Mem*p);
SQLITE_PRIVATE int sqlcipher_sqlite3VdbeMemFinalize(Mem*, FuncDef*);
#ifndef SQLITE_OMIT_WINDOWFUNC
SQLITE_PRIVATE int sqlcipher_sqlite3VdbeMemAggValue(Mem*, Mem*, FuncDef*);
@@ -26517,7 +22907,8 @@ SQLITE_PRIVATE void sqlcipher_sqlite3VdbeFrameMemDel(void*); /* Destructor
SQLITE_PRIVATE void sqlcipher_sqlite3VdbeFrameDelete(VdbeFrame*); /* Actually deletes the Frame */
SQLITE_PRIVATE int sqlcipher_sqlite3VdbeFrameRestore(VdbeFrame *);
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
-SQLITE_PRIVATE void sqlcipher_sqlite3VdbePreUpdateHook(Vdbe*,VdbeCursor*,int,const char*,Table*,i64,int);
+SQLITE_PRIVATE void sqlcipher_sqlite3VdbePreUpdateHook(
+ Vdbe*,VdbeCursor*,int,const char*,Table*,i64,int,int);
#endif
SQLITE_PRIVATE int sqlcipher_sqlite3VdbeTransferError(Vdbe *p);
@@ -26901,8 +23292,7 @@ SQLITE_API int sqlcipher_sqlite3_db_status(
db->pnBytesFreed = &nByte;
for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pNext){
- sqlcipher_sqlite3VdbeClearObject(db, pVdbe);
- sqlcipher_sqlite3DbFree(db, pVdbe);
+ sqlcipher_sqlite3VdbeDelete(pVdbe);
}
db->pnBytesFreed = 0;
@@ -27466,8 +23856,10 @@ static void clearYMD_HMS_TZ(DateTime *p){
** is available. This routine returns 0 on success and
** non-zero on any kind of error.
**
-** If the sqlcipher_sqlite3GlobalConfig.bLocaltimeFault variable is true then this
-** routine will always fail.
+** If the sqlcipher_sqlite3GlobalConfig.bLocaltimeFault variable is non-zero then this
+** routine will always fail. If bLocaltimeFault is nonzero and
+** sqlcipher_sqlite3GlobalConfig.xAltLocaltime is not NULL, then xAltLocaltime() is
+** invoked in place of the OS-defined localtime() function.
**
** EVIDENCE-OF: R-62172-00036 In this implementation, the standard C
** library function localtime_r() is used to assist in the calculation of
@@ -27483,14 +23875,30 @@ static int osLocaltime(time_t *t, struct tm *pTm){
sqlcipher_sqlite3_mutex_enter(mutex);
pX = localtime(t);
#ifndef SQLITE_UNTESTABLE
- if( sqlcipher_sqlite3GlobalConfig.bLocaltimeFault ) pX = 0;
+ if( sqlcipher_sqlite3GlobalConfig.bLocaltimeFault ){
+ if( sqlcipher_sqlite3GlobalConfig.xAltLocaltime!=0
+ && 0==sqlcipher_sqlite3GlobalConfig.xAltLocaltime((const void*)t,(void*)pTm)
+ ){
+ pX = pTm;
+ }else{
+ pX = 0;
+ }
+ }
#endif
if( pX ) *pTm = *pX;
+#if SQLITE_THREADSAFE>0
sqlcipher_sqlite3_mutex_leave(mutex);
+#endif
rc = pX==0;
#else
#ifndef SQLITE_UNTESTABLE
- if( sqlcipher_sqlite3GlobalConfig.bLocaltimeFault ) return 1;
+ if( sqlcipher_sqlite3GlobalConfig.bLocaltimeFault ){
+ if( sqlcipher_sqlite3GlobalConfig.xAltLocaltime!=0 ){
+ return sqlcipher_sqlite3GlobalConfig.xAltLocaltime((const void*)t,(void*)pTm);
+ }else{
+ return 1;
+ }
+ }
#endif
#if HAVE_LOCALTIME_R
rc = localtime_r(t, pTm)==0;
@@ -27505,67 +23913,56 @@ static int osLocaltime(time_t *t, struct tm *pTm){
#ifndef SQLITE_OMIT_LOCALTIME
/*
-** Compute the difference (in milliseconds) between localtime and UTC
-** (a.k.a. GMT) for the time value p where p is in UTC. If no error occurs,
-** return this value and set *pRc to SQLITE_OK.
-**
-** Or, if an error does occur, set *pRc to SQLITE_ERROR. The returned value
-** is undefined in this case.
+** Assuming the input DateTime is UTC, move it to its localtime equivalent.
*/
-static sqlcipher_sqlite3_int64 localtimeOffset(
- DateTime *p, /* Date at which to calculate offset */
- sqlcipher_sqlite3_context *pCtx, /* Write error here if one occurs */
- int *pRc /* OUT: Error code. SQLITE_OK or ERROR */
+static int toLocaltime(
+ DateTime *p, /* Date at which to calculate offset */
+ sqlcipher_sqlite3_context *pCtx /* Write error here if one occurs */
){
- DateTime x, y;
time_t t;
struct tm sLocal;
+ int iYearDiff;
/* Initialize the contents of sLocal to avoid a compiler warning. */
memset(&sLocal, 0, sizeof(sLocal));
- x = *p;
- computeYMD_HMS(&x);
- if( x.Y<1971 || x.Y>=2038 ){
+ computeJD(p);
+ if( p->iJD<2108667600*(i64)100000 /* 1970-01-01 */
+ || p->iJD>2130141456*(i64)100000 /* 2038-01-18 */
+ ){
/* 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;
- x.h = 0;
- x.m = 0;
- x.s = 0.0;
- } else {
- int s = (int)(x.s + 0.5);
- x.s = s;
+ DateTime x = *p;
+ computeYMD_HMS(&x);
+ iYearDiff = (2000 + x.Y%4) - x.Y;
+ x.Y += iYearDiff;
+ x.validJD = 0;
+ computeJD(&x);
+ t = (time_t)(x.iJD/1000 - 21086676*(i64)10000);
+ }else{
+ iYearDiff = 0;
+ t = (time_t)(p->iJD/1000 - 21086676*(i64)10000);
}
- x.tz = 0;
- x.validJD = 0;
- computeJD(&x);
- t = (time_t)(x.iJD/1000 - 21086676*(i64)10000);
if( osLocaltime(&t, &sLocal) ){
sqlcipher_sqlite3_result_error(pCtx, "local time unavailable", -1);
- *pRc = SQLITE_ERROR;
- return 0;
+ return SQLITE_ERROR;
}
- y.Y = sLocal.tm_year + 1900;
- y.M = sLocal.tm_mon + 1;
- y.D = sLocal.tm_mday;
- y.h = sLocal.tm_hour;
- y.m = sLocal.tm_min;
- y.s = sLocal.tm_sec;
- y.validYMD = 1;
- y.validHMS = 1;
- y.validJD = 0;
- y.rawS = 0;
- y.validTZ = 0;
- y.isError = 0;
- computeJD(&y);
- *pRc = SQLITE_OK;
- return y.iJD - x.iJD;
+ p->Y = sLocal.tm_year + 1900 - iYearDiff;
+ p->M = sLocal.tm_mon + 1;
+ p->D = sLocal.tm_mday;
+ p->h = sLocal.tm_hour;
+ p->m = sLocal.tm_min;
+ p->s = sLocal.tm_sec + (p->iJD%1000)*0.001;
+ p->validYMD = 1;
+ p->validHMS = 1;
+ p->validJD = 0;
+ p->rawS = 0;
+ p->validTZ = 0;
+ p->isError = 0;
+ return SQLITE_OK;
}
#endif /* SQLITE_OMIT_LOCALTIME */
@@ -27578,18 +23975,17 @@ static sqlcipher_sqlite3_int64 localtimeOffset(
** of several units of time.
*/
static const struct {
- u8 eType; /* Transformation type code */
- u8 nName; /* Length of th name */
- char *zName; /* Name of the transformation */
- double rLimit; /* Maximum NNN value for this transform */
- double rXform; /* Constant used for this transform */
+ u8 nName; /* Length of the name */
+ char zName[7]; /* Name of the transformation */
+ float rLimit; /* Maximum NNN value for this transform */
+ float rXform; /* Constant used for this transform */
} aXformType[] = {
- { 0, 6, "second", 464269060800.0, 1000.0 },
- { 0, 6, "minute", 7737817680.0, 60000.0 },
- { 0, 4, "hour", 128963628.0, 3600000.0 },
- { 0, 3, "day", 5373485.0, 86400000.0 },
- { 1, 5, "month", 176546.0, 2592000000.0 },
- { 2, 4, "year", 14713.0, 31536000000.0 },
+ { 6, "second", 4.6427e+14, 1.0 },
+ { 6, "minute", 7.7379e+12, 60.0 },
+ { 4, "hour", 1.2897e+11, 3600.0 },
+ { 3, "day", 5373485.0, 86400.0 },
+ { 5, "month", 176546.0, 2592000.0 },
+ { 4, "year", 14713.0, 31536000.0 },
};
/*
@@ -27620,11 +24016,55 @@ static int parseModifier(
sqlcipher_sqlite3_context *pCtx, /* Function context */
const char *z, /* The text of the modifier */
int n, /* Length of zMod in bytes */
- DateTime *p /* The date/time value to be modified */
+ DateTime *p, /* The date/time value to be modified */
+ int idx /* Parameter index of the modifier */
){
int rc = 1;
double r;
switch(sqlcipher_sqlite3UpperToLower[(u8)z[0]] ){
+ case 'a': {
+ /*
+ ** auto
+ **
+ ** If rawS is available, then interpret as a julian day number, or
+ ** a unix timestamp, depending on its magnitude.
+ */
+ if( sqlcipher_sqlite3_stricmp(z, "auto")==0 ){
+ if( idx>1 ) return 1; /* IMP: R-33611-57934 */
+ if( !p->rawS || p->validJD ){
+ rc = 0;
+ p->rawS = 0;
+ }else if( p->s>=-21086676*(i64)10000 /* -4713-11-24 12:00:00 */
+ && p->s<=(25340230*(i64)10000)+799 /* 9999-12-31 23:59:59 */
+ ){
+ r = p->s*1000.0 + 210866760000000.0;
+ clearYMD_HMS_TZ(p);
+ p->iJD = (sqlcipher_sqlite3_int64)(r + 0.5);
+ p->validJD = 1;
+ p->rawS = 0;
+ rc = 0;
+ }
+ }
+ break;
+ }
+ case 'j': {
+ /*
+ ** julianday
+ **
+ ** Always interpret the prior number as a julian-day value. If this
+ ** is not the first modifier, or if the prior argument is not a numeric
+ ** value in the allowed range of julian day numbers understood by
+ ** SQLite (0..5373484.5) then the result will be NULL.
+ */
+ if( sqlcipher_sqlite3_stricmp(z, "julianday")==0 ){
+ if( idx>1 ) return 1; /* IMP: R-31176-64601 */
+ if( p->validJD && p->rawS ){
+ rc = 0;
+ p->rawS = 0;
+ }
+ }
+ break;
+ }
#ifndef SQLITE_OMIT_LOCALTIME
case 'l': {
/* localtime
@@ -27633,9 +24073,7 @@ static int parseModifier(
** show local time.
*/
if( sqlcipher_sqlite3_stricmp(z, "localtime")==0 && sqlcipher_sqlite3NotPureFunc(pCtx) ){
- computeJD(p);
- p->iJD += localtimeOffset(p, pCtx, &rc);
- clearYMD_HMS_TZ(p);
+ rc = toLocaltime(p, pCtx);
}
break;
}
@@ -27648,6 +24086,7 @@ static int parseModifier(
** seconds since 1970. Convert to a real julian day number.
*/
if( sqlcipher_sqlite3_stricmp(z, "unixepoch")==0 && p->rawS ){
+ if( idx>1 ) return 1; /* IMP: R-49255-55373 */
r = p->s*1000.0 + 210866760000000.0;
if( r>=0.0 && r<464269060800000.0 ){
clearYMD_HMS_TZ(p);
@@ -27660,18 +24099,31 @@ static int parseModifier(
#ifndef SQLITE_OMIT_LOCALTIME
else if( sqlcipher_sqlite3_stricmp(z, "utc")==0 && sqlcipher_sqlite3NotPureFunc(pCtx) ){
if( p->tzSet==0 ){
- sqlcipher_sqlite3_int64 c1;
+ i64 iOrigJD; /* Original localtime */
+ i64 iGuess; /* Guess at the corresponding utc time */
+ int cnt = 0; /* Safety to prevent infinite loop */
+ int iErr; /* Guess is off by this much */
+
computeJD(p);
- c1 = localtimeOffset(p, pCtx, &rc);
- if( rc==SQLITE_OK ){
- p->iJD -= c1;
- clearYMD_HMS_TZ(p);
- p->iJD += c1 - localtimeOffset(p, pCtx, &rc);
- }
+ iGuess = iOrigJD = p->iJD;
+ iErr = 0;
+ do{
+ DateTime new;
+ memset(&new, 0, sizeof(new));
+ iGuess -= iErr;
+ new.iJD = iGuess;
+ new.validJD = 1;
+ rc = toLocaltime(&new, pCtx);
+ if( rc ) return rc;
+ computeJD(&new);
+ iErr = new.iJD - iOrigJD;
+ }while( iErr && cnt++<3 );
+ memset(p, 0, sizeof(*p));
+ p->iJD = iGuess;
+ p->validJD = 1;
p->tzSet = 1;
- }else{
- rc = SQLITE_OK;
}
+ rc = SQLITE_OK;
}
#endif
break;
@@ -27787,9 +24239,10 @@ static int parseModifier(
&& sqlcipher_sqlite3_strnicmp(aXformType[i].zName, z, n)==0
&& r>-aXformType[i].rLimit && r<aXformType[i].rLimit
){
- switch( aXformType[i].eType ){
- case 1: { /* Special processing to add months */
+ switch( i ){
+ case 4: { /* Special processing to add months */
int x;
+ assert( strcmp(aXformType[i].zName,"month")==0 );
computeYMD_HMS(p);
p->M += (int)r;
x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12;
@@ -27799,8 +24252,9 @@ static int parseModifier(
r -= (int)r;
break;
}
- case 2: { /* Special processing to add years */
+ case 5: { /* Special processing to add years */
int y = (int)r;
+ assert( strcmp(aXformType[i].zName,"year")==0 );
computeYMD_HMS(p);
p->Y += y;
p->validJD = 0;
@@ -27809,7 +24263,7 @@ static int parseModifier(
}
}
computeJD(p);
- p->iJD += (sqlcipher_sqlite3_int64)(r*aXformType[i].rXform + rRounder);
+ p->iJD += (sqlcipher_sqlite3_int64)(r*1000.0*aXformType[i].rXform + rRounder);
rc = 0;
break;
}
@@ -27844,6 +24298,7 @@ static int isDate(
int eType;
memset(p, 0, sizeof(*p));
if( argc==0 ){
+ if( !sqlcipher_sqlite3NotPureFunc(context) ) return 1;
return setDateTimeToCurrent(context, p);
}
if( (eType = sqlcipher_sqlite3_value_type(argv[0]))==SQLITE_FLOAT
@@ -27858,7 +24313,7 @@ static int isDate(
for(i=1; i<argc; i++){
z = sqlcipher_sqlite3_value_text(argv[i]);
n = sqlcipher_sqlite3_value_bytes(argv[i]);
- if( z==0 || parseModifier(context, (char*)z, n, p) ) return 1;
+ if( z==0 || parseModifier(context, (char*)z, n, p, i) ) return 1;
}
computeJD(p);
if( p->isError || !validJulianDay(p->iJD) ) return 1;
@@ -27889,6 +24344,24 @@ static void juliandayFunc(
}
/*
+** unixepoch( TIMESTRING, MOD, MOD, ...)
+**
+** Return the number of seconds (including fractional seconds) since
+** the unix epoch of 1970-01-01 00:00:00 GMT.
+*/
+static void unixepochFunc(
+ sqlcipher_sqlite3_context *context,
+ int argc,
+ sqlcipher_sqlite3_value **argv
+){
+ DateTime x;
+ if( isDate(context, argc, argv, &x)==0 ){
+ computeJD(&x);
+ sqlcipher_sqlite3_result_int64(context, x.iJD/1000 - 21086676*(i64)10000);
+ }
+}
+
+/*
** datetime( TIMESTRING, MOD, MOD, ...)
**
** Return YYYY-MM-DD HH:MM:SS
@@ -27900,11 +24373,38 @@ static void datetimeFunc(
){
DateTime x;
if( isDate(context, argc, argv, &x)==0 ){
- char zBuf[100];
+ int Y, s;
+ char zBuf[24];
computeYMD_HMS(&x);
- sqlcipher_sqlite3_snprintf(sizeof(zBuf), zBuf, "%04d-%02d-%02d %02d:%02d:%02d",
- x.Y, x.M, x.D, x.h, x.m, (int)(x.s));
- sqlcipher_sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
+ Y = x.Y;
+ if( Y<0 ) Y = -Y;
+ zBuf[1] = '0' + (Y/1000)%10;
+ zBuf[2] = '0' + (Y/100)%10;
+ zBuf[3] = '0' + (Y/10)%10;
+ zBuf[4] = '0' + (Y)%10;
+ zBuf[5] = '-';
+ zBuf[6] = '0' + (x.M/10)%10;
+ zBuf[7] = '0' + (x.M)%10;
+ zBuf[8] = '-';
+ zBuf[9] = '0' + (x.D/10)%10;
+ zBuf[10] = '0' + (x.D)%10;
+ zBuf[11] = ' ';
+ zBuf[12] = '0' + (x.h/10)%10;
+ zBuf[13] = '0' + (x.h)%10;
+ zBuf[14] = ':';
+ zBuf[15] = '0' + (x.m/10)%10;
+ zBuf[16] = '0' + (x.m)%10;
+ zBuf[17] = ':';
+ s = (int)x.s;
+ zBuf[18] = '0' + (s/10)%10;
+ zBuf[19] = '0' + (s)%10;
+ zBuf[20] = 0;
+ if( x.Y<0 ){
+ zBuf[0] = '-';
+ sqlcipher_sqlite3_result_text(context, zBuf, 20, SQLITE_TRANSIENT);
+ }else{
+ sqlcipher_sqlite3_result_text(context, &zBuf[1], 19, SQLITE_TRANSIENT);
+ }
}
}
@@ -27920,10 +24420,20 @@ static void timeFunc(
){
DateTime x;
if( isDate(context, argc, argv, &x)==0 ){
- char zBuf[100];
+ int s;
+ char zBuf[16];
computeHMS(&x);
- sqlcipher_sqlite3_snprintf(sizeof(zBuf), zBuf, "%02d:%02d:%02d", x.h, x.m, (int)x.s);
- sqlcipher_sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
+ zBuf[0] = '0' + (x.h/10)%10;
+ zBuf[1] = '0' + (x.h)%10;
+ zBuf[2] = ':';
+ zBuf[3] = '0' + (x.m/10)%10;
+ zBuf[4] = '0' + (x.m)%10;
+ zBuf[5] = ':';
+ s = (int)x.s;
+ zBuf[6] = '0' + (s/10)%10;
+ zBuf[7] = '0' + (s)%10;
+ zBuf[8] = 0;
+ sqlcipher_sqlite3_result_text(context, zBuf, 8, SQLITE_TRANSIENT);
}
}
@@ -27939,10 +24449,28 @@ static void dateFunc(
){
DateTime x;
if( isDate(context, argc, argv, &x)==0 ){
- char zBuf[100];
+ int Y;
+ char zBuf[16];
computeYMD(&x);
- sqlcipher_sqlite3_snprintf(sizeof(zBuf), zBuf, "%04d-%02d-%02d", x.Y, x.M, x.D);
- sqlcipher_sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
+ Y = x.Y;
+ if( Y<0 ) Y = -Y;
+ zBuf[1] = '0' + (Y/1000)%10;
+ zBuf[2] = '0' + (Y/100)%10;
+ zBuf[3] = '0' + (Y/10)%10;
+ zBuf[4] = '0' + (Y)%10;
+ zBuf[5] = '-';
+ zBuf[6] = '0' + (x.M/10)%10;
+ zBuf[7] = '0' + (x.M)%10;
+ zBuf[8] = '-';
+ zBuf[9] = '0' + (x.D/10)%10;
+ zBuf[10] = '0' + (x.D)%10;
+ zBuf[11] = 0;
+ if( x.Y<0 ){
+ zBuf[0] = '-';
+ sqlcipher_sqlite3_result_text(context, zBuf, 11, SQLITE_TRANSIENT);
+ }else{
+ sqlcipher_sqlite3_result_text(context, &zBuf[1], 10, SQLITE_TRANSIENT);
+ }
}
}
@@ -27971,131 +24499,100 @@ static void strftimeFunc(
sqlcipher_sqlite3_value **argv
){
DateTime x;
- u64 n;
size_t i,j;
- char *z;
sqlcipher_sqlite3 *db;
const char *zFmt;
- char zBuf[100];
+ sqlcipher_sqlite3_str sRes;
+
+
if( argc==0 ) return;
zFmt = (const char*)sqlcipher_sqlite3_value_text(argv[0]);
if( zFmt==0 || isDate(context, argc-1, argv+1, &x) ) return;
db = sqlcipher_sqlite3_context_db_handle(context);
- for(i=0, n=1; zFmt[i]; i++, n++){
- if( zFmt[i]=='%' ){
- switch( zFmt[i+1] ){
- case 'd':
- case 'H':
- case 'm':
- case 'M':
- case 'S':
- case 'W':
- n++;
- /* fall thru */
- case 'w':
- case '%':
- break;
- case 'f':
- n += 8;
- break;
- case 'j':
- n += 3;
- break;
- case 'Y':
- n += 8;
- break;
- case 's':
- case 'J':
- n += 50;
- break;
- default:
- return; /* ERROR. return a NULL */
- }
- i++;
- }
- }
- testcase( n==sizeof(zBuf)-1 );
- testcase( n==sizeof(zBuf) );
- testcase( n==(u64)db->aLimit[SQLITE_LIMIT_LENGTH]+1 );
- testcase( n==(u64)db->aLimit[SQLITE_LIMIT_LENGTH] );
- if( n<sizeof(zBuf) ){
- z = zBuf;
- }else if( n>(u64)db->aLimit[SQLITE_LIMIT_LENGTH] ){
- sqlcipher_sqlite3_result_error_toobig(context);
- return;
- }else{
- z = sqlcipher_sqlite3DbMallocRawNN(db, (int)n);
- if( z==0 ){
- sqlcipher_sqlite3_result_error_nomem(context);
- return;
- }
- }
+ sqlcipher_sqlite3StrAccumInit(&sRes, 0, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]);
+
computeJD(&x);
computeYMD_HMS(&x);
for(i=j=0; zFmt[i]; i++){
- if( zFmt[i]!='%' ){
- z[j++] = zFmt[i];
- }else{
- i++;
- switch( zFmt[i] ){
- case 'd': sqlcipher_sqlite3_snprintf(3, &z[j],"%02d",x.D); j+=2; break;
- case 'f': {
- double s = x.s;
- if( s>59.999 ) s = 59.999;
- sqlcipher_sqlite3_snprintf(7, &z[j],"%06.3f", s);
- j += sqlcipher_sqlite3Strlen30(&z[j]);
- break;
- }
- case 'H': sqlcipher_sqlite3_snprintf(3, &z[j],"%02d",x.h); j+=2; break;
- case 'W': /* Fall thru */
- case 'j': {
- int nDay; /* Number of days since 1st day of year */
- DateTime y = x;
- y.validJD = 0;
- y.M = 1;
- y.D = 1;
- computeJD(&y);
- nDay = (int)((x.iJD-y.iJD+43200000)/86400000);
- if( zFmt[i]=='W' ){
- int wd; /* 0=Monday, 1=Tuesday, ... 6=Sunday */
- wd = (int)(((x.iJD+43200000)/86400000)%7);
- sqlcipher_sqlite3_snprintf(3, &z[j],"%02d",(nDay+7-wd)/7);
- j += 2;
- }else{
- sqlcipher_sqlite3_snprintf(4, &z[j],"%03d",nDay+1);
- j += 3;
- }
- break;
- }
- case 'J': {
- sqlcipher_sqlite3_snprintf(20, &z[j],"%.16g",x.iJD/86400000.0);
- j+=sqlcipher_sqlite3Strlen30(&z[j]);
- break;
- }
- case 'm': sqlcipher_sqlite3_snprintf(3, &z[j],"%02d",x.M); j+=2; break;
- case 'M': sqlcipher_sqlite3_snprintf(3, &z[j],"%02d",x.m); j+=2; break;
- case 's': {
- i64 iS = (i64)(x.iJD/1000 - 21086676*(i64)10000);
- sqlcipher_sqlite3Int64ToText(iS, &z[j]);
- j += sqlcipher_sqlite3Strlen30(&z[j]);
- break;
- }
- case 'S': sqlcipher_sqlite3_snprintf(3,&z[j],"%02d",(int)x.s); j+=2; break;
- case 'w': {
- z[j++] = (char)(((x.iJD+129600000)/86400000) % 7) + '0';
- break;
- }
- case 'Y': {
- sqlcipher_sqlite3_snprintf(5,&z[j],"%04d",x.Y); j+=sqlcipher_sqlite3Strlen30(&z[j]);
- break;
+ if( zFmt[i]!='%' ) continue;
+ if( j<i ) sqlcipher_sqlite3_str_append(&sRes, zFmt+j, (int)(i-j));
+ i++;
+ j = i + 1;
+ switch( zFmt[i] ){
+ case 'd': {
+ sqlcipher_sqlite3_str_appendf(&sRes, "%02d", x.D);
+ break;
+ }
+ case 'f': {
+ double s = x.s;
+ if( s>59.999 ) s = 59.999;
+ sqlcipher_sqlite3_str_appendf(&sRes, "%06.3f", s);
+ break;
+ }
+ case 'H': {
+ sqlcipher_sqlite3_str_appendf(&sRes, "%02d", x.h);
+ break;
+ }
+ case 'W': /* Fall thru */
+ case 'j': {
+ int nDay; /* Number of days since 1st day of year */
+ DateTime y = x;
+ y.validJD = 0;
+ y.M = 1;
+ y.D = 1;
+ computeJD(&y);
+ nDay = (int)((x.iJD-y.iJD+43200000)/86400000);
+ if( zFmt[i]=='W' ){
+ int wd; /* 0=Monday, 1=Tuesday, ... 6=Sunday */
+ wd = (int)(((x.iJD+43200000)/86400000)%7);
+ sqlcipher_sqlite3_str_appendf(&sRes,"%02d",(nDay+7-wd)/7);
+ }else{
+ sqlcipher_sqlite3_str_appendf(&sRes,"%03d",nDay+1);
}
- default: z[j++] = '%'; break;
+ break;
+ }
+ case 'J': {
+ sqlcipher_sqlite3_str_appendf(&sRes,"%.16g",x.iJD/86400000.0);
+ break;
+ }
+ case 'm': {
+ sqlcipher_sqlite3_str_appendf(&sRes,"%02d",x.M);
+ break;
+ }
+ case 'M': {
+ sqlcipher_sqlite3_str_appendf(&sRes,"%02d",x.m);
+ break;
+ }
+ case 's': {
+ i64 iS = (i64)(x.iJD/1000 - 21086676*(i64)10000);
+ sqlcipher_sqlite3_str_appendf(&sRes,"%lld",iS);
+ break;
+ }
+ case 'S': {
+ sqlcipher_sqlite3_str_appendf(&sRes,"%02d",(int)x.s);
+ break;
+ }
+ case 'w': {
+ sqlcipher_sqlite3_str_appendchar(&sRes, 1,
+ (char)(((x.iJD+129600000)/86400000) % 7) + '0');
+ break;
+ }
+ case 'Y': {
+ sqlcipher_sqlite3_str_appendf(&sRes,"%04d",x.Y);
+ break;
+ }
+ case '%': {
+ sqlcipher_sqlite3_str_appendchar(&sRes, 1, '%');
+ break;
+ }
+ default: {
+ sqlcipher_sqlite3_str_reset(&sRes);
+ return;
}
}
}
- z[j] = 0;
- sqlcipher_sqlite3_result_text(context, z, -1,
- z==zBuf ? SQLITE_TRANSIENT : SQLITE_DYNAMIC);
+ if( j<i ) sqlcipher_sqlite3_str_append(&sRes, zFmt+j, (int)(i-j));
+ sqlcipher_sqlite3ResultStrAccum(context, &sRes);
}
/*
@@ -28195,6 +24692,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3RegisterDateTimeFunctions(void){
static FuncDef aDateTimeFuncs[] = {
#ifndef SQLITE_OMIT_DATETIME_FUNCS
PURE_DATE(julianday, -1, 0, 0, juliandayFunc ),
+ PURE_DATE(unixepoch, -1, 0, 0, unixepochFunc ),
PURE_DATE(date, -1, 0, 0, dateFunc ),
PURE_DATE(time, -1, 0, 0, timeFunc ),
PURE_DATE(datetime, -1, 0, 0, datetimeFunc ),
@@ -28344,6 +24842,8 @@ SQLITE_PRIVATE int sqlcipher_sqlite3OsFileControl(sqlcipher_sqlite3_file *id, in
#ifdef SQLITE_TEST
if( op!=SQLITE_FCNTL_COMMIT_PHASETWO
&& op!=SQLITE_FCNTL_LOCK_TIMEOUT
+ && op!=SQLITE_FCNTL_CKPT_DONE
+ && op!=SQLITE_FCNTL_CKPT_START
){
/* Faults are not injected into COMMIT_PHASETWO because, assuming SQLite
** is using a regular VFS, it is called after the corresponding
@@ -28354,7 +24854,12 @@ SQLITE_PRIVATE int sqlcipher_sqlite3OsFileControl(sqlcipher_sqlite3_file *id, in
** 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. */
+ ** to the user.
+ **
+ ** The CKPT_DONE and CKPT_START file-controls are write-only signals
+ ** to the cksumvfs. Their return code is meaningless and is ignored
+ ** by the SQLite core, so there is no point in simulating OOMs for them.
+ */
DO_OS_MALLOC_TEST(id);
}
#endif
@@ -28369,6 +24874,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3OsSectorSize(sqlcipher_sqlite3_file *id){
return (xSectorSize ? xSectorSize(id) : SQLITE_DEFAULT_SECTOR_SIZE);
}
SQLITE_PRIVATE int sqlcipher_sqlite3OsDeviceCharacteristics(sqlcipher_sqlite3_file *id){
+ if( NEVER(id->pMethods==0) ) return 0;
return id->pMethods->xDeviceCharacteristics(id);
}
#ifndef SQLITE_OMIT_WAL
@@ -28437,7 +24943,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3OsOpen(
SQLITE_PRIVATE int sqlcipher_sqlite3OsDelete(sqlcipher_sqlite3_vfs *pVfs, const char *zPath, int dirSync){
DO_OS_MALLOC_TEST(0);
assert( dirSync==0 || dirSync==1 );
- return pVfs->xDelete(pVfs, zPath, dirSync);
+ return pVfs->xDelete!=0 ? pVfs->xDelete(pVfs, zPath, dirSync) : SQLITE_OK;
}
SQLITE_PRIVATE int sqlcipher_sqlite3OsAccess(
sqlcipher_sqlite3_vfs *pVfs,
@@ -28460,6 +24966,8 @@ SQLITE_PRIVATE int sqlcipher_sqlite3OsFullPathname(
}
#ifndef SQLITE_OMIT_LOAD_EXTENSION
SQLITE_PRIVATE void *sqlcipher_sqlite3OsDlOpen(sqlcipher_sqlite3_vfs *pVfs, const char *zPath){
+ assert( zPath!=0 );
+ assert( strlen(zPath)<=SQLITE_MAX_PATHLEN ); /* tag-20210611-1 */
return pVfs->xDlOpen(pVfs, zPath);
}
SQLITE_PRIVATE void sqlcipher_sqlite3OsDlError(sqlcipher_sqlite3_vfs *pVfs, int nByte, char *zBufOut){
@@ -28521,12 +25029,15 @@ SQLITE_PRIVATE int sqlcipher_sqlite3OsOpenMalloc(
rc = sqlcipher_sqlite3OsOpen(pVfs, zFile, pFile, flags, pOutFlags);
if( rc!=SQLITE_OK ){
sqlcipher_sqlite3_free(pFile);
+ *ppFile = 0;
}else{
*ppFile = pFile;
}
}else{
+ *ppFile = 0;
rc = SQLITE_NOMEM_BKPT;
}
+ assert( *ppFile!=0 || rc!=SQLITE_OK );
return rc;
}
SQLITE_PRIVATE void sqlcipher_sqlite3OsCloseFree(sqlcipher_sqlite3_file *pFile){
@@ -29244,7 +25755,7 @@ static void adjustStats(int iSize, int increment){
** This routine checks the guards at either end of the allocation and
** if they are incorrect it asserts.
*/
-static struct MemBlockHdr *sqlcipher_sqlite3MemsysGetHeader(void *pAllocation){
+static struct MemBlockHdr *sqlcipher_sqlite3MemsysGetHeader(const void *pAllocation){
struct MemBlockHdr *p;
int *pInt;
u8 *pU8;
@@ -29491,7 +26002,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3MemdebugSetType(void *p, u8 eType){
**
** assert( sqlcipher_sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
*/
-SQLITE_PRIVATE int sqlcipher_sqlite3MemdebugHasType(void *p, u8 eType){
+SQLITE_PRIVATE int sqlcipher_sqlite3MemdebugHasType(const void *p, u8 eType){
int rc = 1;
if( p && sqlcipher_sqlite3GlobalConfig.m.xFree==sqlcipher_sqlite3MemFree ){
struct MemBlockHdr *pHdr;
@@ -29513,7 +26024,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3MemdebugHasType(void *p, u8 eType){
**
** assert( sqlcipher_sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) );
*/
-SQLITE_PRIVATE int sqlcipher_sqlite3MemdebugNoType(void *p, u8 eType){
+SQLITE_PRIVATE int sqlcipher_sqlite3MemdebugNoType(const void *p, u8 eType){
int rc = 1;
if( p && sqlcipher_sqlite3GlobalConfig.m.xFree==sqlcipher_sqlite3MemFree ){
struct MemBlockHdr *pHdr;
@@ -30736,8 +27247,13 @@ static void *memsys5Realloc(void *pPrior, int nBytes){
*/
static int memsys5Roundup(int n){
int iFullSz;
- if( n > 0x40000000 ) return 0;
- for(iFullSz=mem5.szAtom; iFullSz<n; iFullSz *= 2);
+ if( n<=mem5.szAtom*2 ){
+ if( n<=mem5.szAtom ) return mem5.szAtom;
+ return mem5.szAtom*2;
+ }
+ if( n>0x40000000 ) return 0;
+ for(iFullSz=mem5.szAtom*8; iFullSz<n; iFullSz *= 4);
+ if( (iFullSz/2)>=n ) return iFullSz/2;
return iFullSz;
}
@@ -31891,205 +28407,7 @@ SQLITE_PRIVATE sqlcipher_sqlite3_mutex_methods const *sqlcipher_sqlite3DefaultMu
/*
** 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
-
-/*
-** 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 and x86_64 class CPUs.
-*/
-#ifndef SQLITE_HWTIME_H
-#define SQLITE_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(__STRICT_ANSI__) && \
- (defined(__GNUC__) || defined(_MSC_VER)) && \
- (defined(i386) || defined(__i386__) || defined(_M_IX86))
-
- #if defined(__GNUC__)
-
- __inline__ sqlite_uint64 sqlcipher_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 sqlcipher_sqlite3Hwtime(void){
- __asm {
- rdtsc
- ret ; return value at EDX:EAX
- }
- }
-
- #endif
-
-#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__))
-
- __inline__ sqlite_uint64 sqlcipher_sqlite3Hwtime(void){
- unsigned long val;
- __asm__ __volatile__ ("rdtsc" : "=A" (val));
- return val;
- }
-
-#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__))
-
- __inline__ sqlite_uint64 sqlcipher_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
-
- /*
- ** asm() is needed for hardware timing support. Without asm(),
- ** disable the sqlcipher_sqlite3Hwtime() routine.
- **
- ** sqlcipher_sqlite3Hwtime() is only used for some obscure debugging
- ** and analysis configurations, not in any deliverable, so this
- ** should not be a great loss.
- */
-SQLITE_PRIVATE sqlite_uint64 sqlcipher_sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
-
-#endif
-
-#endif /* !defined(SQLITE_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=sqlcipher_sqlite3Hwtime()
-#define TIMER_END g_elapsed=sqlcipher_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.
-*/
-#if defined(SQLITE_TEST)
-SQLITE_API extern int sqlcipher_sqlite3_io_error_hit;
-SQLITE_API extern int sqlcipher_sqlite3_io_error_hardhit;
-SQLITE_API extern int sqlcipher_sqlite3_io_error_pending;
-SQLITE_API extern int sqlcipher_sqlite3_io_error_persist;
-SQLITE_API extern int sqlcipher_sqlite3_io_error_benign;
-SQLITE_API extern int sqlcipher_sqlite3_diskfull_pending;
-SQLITE_API extern int sqlcipher_sqlite3_diskfull;
-#define SimulateIOErrorBenign(X) sqlcipher_sqlite3_io_error_benign=(X)
-#define SimulateIOError(CODE) \
- if( (sqlcipher_sqlite3_io_error_persist && sqlcipher_sqlite3_io_error_hit) \
- || sqlcipher_sqlite3_io_error_pending-- == 1 ) \
- { local_ioerr(); CODE; }
-static void local_ioerr(){
- IOTRACE(("IOERR\n"));
- sqlcipher_sqlite3_io_error_hit++;
- if( !sqlcipher_sqlite3_io_error_benign ) sqlcipher_sqlite3_io_error_hardhit++;
-}
-#define SimulateDiskfullError(CODE) \
- if( sqlcipher_sqlite3_diskfull_pending ){ \
- if( sqlcipher_sqlite3_diskfull_pending == 1 ){ \
- local_ioerr(); \
- sqlcipher_sqlite3_diskfull = 1; \
- sqlcipher_sqlite3_io_error_hit = 1; \
- CODE; \
- }else{ \
- sqlcipher_sqlite3_diskfull_pending--; \
- } \
- }
-#else
-#define SimulateIOErrorBenign(X)
-#define SimulateIOError(A)
-#define SimulateDiskfullError(A)
-#endif /* defined(SQLITE_TEST) */
-
-/*
-** When testing, keep a count of the number of open files.
-*/
-#if defined(SQLITE_TEST)
-SQLITE_API extern int sqlcipher_sqlite3_open_file_count;
-#define OpenCounter(X) sqlcipher_sqlite3_open_file_count+=(X)
-#else
-#define OpenCounter(X)
-#endif /* defined(SQLITE_TEST) */
-
-#endif /* !defined(_OS_COMMON_H_) */
-
-/************** End of os_common.h *******************************************/
-/************** Continuing where we left off in mutex_w32.c ******************/
+/* #include "os_common.h" */
/*
** Include the header file for the Windows VFS.
@@ -32116,11 +28434,11 @@ SQLITE_API extern int sqlcipher_sqlite3_open_file_count;
/*
** Include the primary Windows SDK header file.
*/
-/* #include "windows.h" */
+#include "windows.h"
#ifdef __CYGWIN__
# include <sys/cygwin.h>
-/* # include <errno.h> ** amalgamator: dontcache ** */
+# include <errno.h> /* amalgamator: dontcache */
#endif
/*
@@ -32727,7 +29045,6 @@ SQLITE_PRIVATE int sqlcipher_sqlite3MallocInit(void){
if( sqlcipher_sqlite3GlobalConfig.m.xMalloc==0 ){
sqlcipher_sqlite3MemSetDefault();
}
- memset(&mem0, 0, sizeof(mem0));
mem0.mutex = sqlcipher_sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
if( sqlcipher_sqlite3GlobalConfig.pPage==0 || sqlcipher_sqlite3GlobalConfig.szPage<512
|| sqlcipher_sqlite3GlobalConfig.nPage<=0 ){
@@ -32894,7 +29211,7 @@ SQLITE_API void *sqlcipher_sqlite3_malloc64(sqlcipher_sqlite3_uint64 n){
** TRUE if p is a lookaside memory allocation from db
*/
#ifndef SQLITE_OMIT_LOOKASIDE
-static int isLookaside(sqlcipher_sqlite3 *db, void *p){
+static int isLookaside(sqlcipher_sqlite3 *db, const void *p){
return SQLITE_WITHIN(p, db->lookaside.pStart, db->lookaside.pEnd);
}
#else
@@ -32905,18 +29222,18 @@ static int isLookaside(sqlcipher_sqlite3 *db, void *p){
** Return the size of a memory allocation previously obtained from
** sqlcipher_sqlite3Malloc() or sqlcipher_sqlite3_malloc().
*/
-SQLITE_PRIVATE int sqlcipher_sqlite3MallocSize(void *p){
+SQLITE_PRIVATE int sqlcipher_sqlite3MallocSize(const void *p){
assert( sqlcipher_sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
- return sqlcipher_sqlite3GlobalConfig.m.xSize(p);
+ return sqlcipher_sqlite3GlobalConfig.m.xSize((void*)p);
}
-static int lookasideMallocSize(sqlcipher_sqlite3 *db, void *p){
+static int lookasideMallocSize(sqlcipher_sqlite3 *db, const void *p){
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
return p<db->lookaside.pMiddle ? db->lookaside.szTrue : LOOKASIDE_SMALL;
#else
return db->lookaside.szTrue;
#endif
}
-SQLITE_PRIVATE int sqlcipher_sqlite3DbMallocSize(sqlcipher_sqlite3 *db, void *p){
+SQLITE_PRIVATE int sqlcipher_sqlite3DbMallocSize(sqlcipher_sqlite3 *db, const void *p){
assert( p!=0 );
#ifdef SQLITE_DEBUG
if( db==0 || !isLookaside(db,p) ){
@@ -32943,7 +29260,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3DbMallocSize(sqlcipher_sqlite3 *db, void *p)
}
}
}
- return sqlcipher_sqlite3GlobalConfig.m.xSize(p);
+ return sqlcipher_sqlite3GlobalConfig.m.xSize((void*)p);
}
SQLITE_API sqlcipher_sqlite3_uint64 sqlcipher_sqlite3_msize(void *p){
assert( sqlcipher_sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) );
@@ -33328,8 +29645,9 @@ SQLITE_PRIVATE char *sqlcipher_sqlite3DbSpanDup(sqlcipher_sqlite3 *db, const cha
** Free any prior content in *pz and replace it with a copy of zNew.
*/
SQLITE_PRIVATE void sqlcipher_sqlite3SetString(char **pz, sqlcipher_sqlite3 *db, const char *zNew){
+ char *z = sqlcipher_sqlite3DbStrDup(db, zNew);
sqlcipher_sqlite3DbFree(db, *pz);
- *pz = sqlcipher_sqlite3DbStrDup(db, zNew);
+ *pz = z;
}
/*
@@ -33337,8 +29655,15 @@ SQLITE_PRIVATE void sqlcipher_sqlite3SetString(char **pz, sqlcipher_sqlite3 *db,
** has happened. This routine will set db->mallocFailed, and also
** temporarily disable the lookaside memory allocator and interrupt
** any running VDBEs.
+**
+** Always return a NULL pointer so that this routine can be invoked using
+**
+** return sqlcipher_sqlite3OomFault(db);
+**
+** and thereby avoid unnecessary stack frame allocations for the overwhelmingly
+** common case where no OOM occurs.
*/
-SQLITE_PRIVATE void sqlcipher_sqlite3OomFault(sqlcipher_sqlite3 *db){
+SQLITE_PRIVATE void *sqlcipher_sqlite3OomFault(sqlcipher_sqlite3 *db){
if( db->mallocFailed==0 && db->bBenignMalloc==0 ){
db->mallocFailed = 1;
if( db->nVdbeExec>0 ){
@@ -33346,9 +29671,16 @@ SQLITE_PRIVATE void sqlcipher_sqlite3OomFault(sqlcipher_sqlite3 *db){
}
DisableLookaside;
if( db->pParse ){
+ Parse *pParse;
+ sqlcipher_sqlite3ErrorMsg(db->pParse, "out of memory");
db->pParse->rc = SQLITE_NOMEM_BKPT;
+ for(pParse=db->pParse->pOuterParse; pParse; pParse = pParse->pOuterParse){
+ pParse->nErr++;
+ pParse->rc = SQLITE_NOMEM;
+ }
}
}
+ return 0;
}
/*
@@ -33437,7 +29769,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ApiExit(sqlcipher_sqlite3* db, int rc){
#define etSQLESCAPE2 10 /* Strings with '\'' doubled and enclosed in '',
NULL pointers replaced by SQL NULL. %Q */
#define etTOKEN 11 /* a pointer to a Token structure */
-#define etSRCLIST 12 /* a pointer to a SrcList */
+#define etSRCITEM 12 /* a pointer to a SrcItem */
#define etPOINTER 13 /* The %p conversion */
#define etSQLESCAPE3 14 /* %w -> Strings with '\"' doubled */
#define etORDINAL 15 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */
@@ -33503,10 +29835,16 @@ static const et_info fmtinfo[] = {
/* All the rest are undocumented and are for internal use only */
{ 'T', 0, 0, etTOKEN, 0, 0 },
- { 'S', 0, 0, etSRCLIST, 0, 0 },
+ { 'S', 0, 0, etSRCITEM, 0, 0 },
{ 'r', 10, 1, etORDINAL, 0, 0 },
};
+/* Notes:
+**
+** %S Takes a pointer to SrcItem. Shows name or database.name
+** %!S Like %S but prefer the zName over the zAlias
+*/
+
/* Floating point constants used for rounding */
static const double arRound[] = {
5.0e-01, 5.0e-02, 5.0e-03, 5.0e-04, 5.0e-05,
@@ -33547,7 +29885,7 @@ static char et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){
/*
** Set the StrAccum object to an error mode.
*/
-static void setStrAccumError(StrAccum *p, u8 eError){
+SQLITE_PRIVATE void sqlcipher_sqlite3StrAccumSetError(StrAccum *p, u8 eError){
assert( eError==SQLITE_NOMEM || eError==SQLITE_TOOBIG );
p->accError = eError;
if( p->mxAlloc ) sqlcipher_sqlite3_str_reset(p);
@@ -33583,12 +29921,12 @@ static char *printfTempBuf(sqlcipher_sqlite3_str *pAccum, sqlcipher_sqlite3_int6
char *z;
if( pAccum->accError ) return 0;
if( n>pAccum->nAlloc && n>pAccum->mxAlloc ){
- setStrAccumError(pAccum, SQLITE_TOOBIG);
+ sqlcipher_sqlite3StrAccumSetError(pAccum, SQLITE_TOOBIG);
return 0;
}
z = sqlcipher_sqlite3DbMallocRaw(pAccum->db, n);
if( z==0 ){
- setStrAccumError(pAccum, SQLITE_NOMEM);
+ sqlcipher_sqlite3StrAccumSetError(pAccum, SQLITE_NOMEM);
}
return z;
}
@@ -34205,8 +30543,8 @@ SQLITE_API void sqlcipher_sqlite3_str_vappendf(
case etSQLESCAPE: /* %q: Escape ' characters */
case etSQLESCAPE2: /* %Q: Escape ' and enclose in '...' */
case etSQLESCAPE3: { /* %w: Escape " characters */
- int i, j, k, n, isnull;
- int needQuote;
+ i64 i, j, k, n;
+ int needQuote, isnull;
char ch;
char q = ((xtype==etSQLESCAPE3)?'"':'\''); /* Quote character */
char *escarg;
@@ -34251,31 +30589,50 @@ SQLITE_API void sqlcipher_sqlite3_str_vappendf(
goto adjust_width_for_utf8;
}
case etTOKEN: {
- Token *pToken;
if( (pAccum->printfFlags & SQLITE_PRINTF_INTERNAL)==0 ) return;
- pToken = va_arg(ap, Token*);
- assert( bArgList==0 );
- if( pToken && pToken->n ){
- sqlcipher_sqlite3_str_append(pAccum, (const char*)pToken->z, pToken->n);
+ if( flag_alternateform ){
+ /* %#T means an Expr pointer that uses Expr.u.zToken */
+ Expr *pExpr = va_arg(ap,Expr*);
+ if( ALWAYS(pExpr) && ALWAYS(!ExprHasProperty(pExpr,EP_IntValue)) ){
+ sqlcipher_sqlite3_str_appendall(pAccum, (const char*)pExpr->u.zToken);
+ sqlcipher_sqlite3RecordErrorOffsetOfExpr(pAccum->db, pExpr);
+ }
+ }else{
+ /* %T means a Token pointer */
+ Token *pToken = va_arg(ap, Token*);
+ assert( bArgList==0 );
+ if( pToken && pToken->n ){
+ sqlcipher_sqlite3_str_append(pAccum, (const char*)pToken->z, pToken->n);
+ sqlcipher_sqlite3RecordErrorByteOffset(pAccum->db, pToken->z);
+ }
}
length = width = 0;
break;
}
- case etSRCLIST: {
- SrcList *pSrc;
- int k;
- struct SrcList_item *pItem;
+ case etSRCITEM: {
+ SrcItem *pItem;
if( (pAccum->printfFlags & SQLITE_PRINTF_INTERNAL)==0 ) return;
- pSrc = va_arg(ap, SrcList*);
- k = va_arg(ap, int);
- pItem = &pSrc->a[k];
+ pItem = va_arg(ap, SrcItem*);
assert( bArgList==0 );
- assert( k>=0 && k<pSrc->nSrc );
- if( pItem->zDatabase ){
- sqlcipher_sqlite3_str_appendall(pAccum, pItem->zDatabase);
- sqlcipher_sqlite3_str_append(pAccum, ".", 1);
+ if( pItem->zAlias && !flag_altform2 ){
+ sqlcipher_sqlite3_str_appendall(pAccum, pItem->zAlias);
+ }else if( pItem->zName ){
+ if( pItem->zDatabase ){
+ sqlcipher_sqlite3_str_appendall(pAccum, pItem->zDatabase);
+ sqlcipher_sqlite3_str_append(pAccum, ".", 1);
+ }
+ sqlcipher_sqlite3_str_appendall(pAccum, pItem->zName);
+ }else if( pItem->zAlias ){
+ sqlcipher_sqlite3_str_appendall(pAccum, pItem->zAlias);
+ }else{
+ Select *pSel = pItem->pSelect;
+ assert( pSel!=0 );
+ if( pSel->selFlags & SF_NestedFrom ){
+ sqlcipher_sqlite3_str_appendf(pAccum, "(join-%u)", pSel->selId);
+ }else{
+ sqlcipher_sqlite3_str_appendf(pAccum, "(subquery-%u)", pSel->selId);
+ }
}
- sqlcipher_sqlite3_str_appendall(pAccum, pItem->zName);
length = width = 0;
break;
}
@@ -34308,6 +30665,44 @@ SQLITE_API void sqlcipher_sqlite3_str_vappendf(
}/* End for loop over the format string */
} /* End of function */
+
+/*
+** The z string points to the first character of a token that is
+** associated with an error. If db does not already have an error
+** byte offset recorded, try to compute the error byte offset for
+** z and set the error byte offset in db.
+*/
+SQLITE_PRIVATE void sqlcipher_sqlite3RecordErrorByteOffset(sqlcipher_sqlite3 *db, const char *z){
+ const Parse *pParse;
+ const char *zText;
+ const char *zEnd;
+ assert( z!=0 );
+ if( NEVER(db==0) ) return;
+ if( db->errByteOffset!=(-2) ) return;
+ pParse = db->pParse;
+ if( NEVER(pParse==0) ) return;
+ zText =pParse->zTail;
+ if( NEVER(zText==0) ) return;
+ zEnd = &zText[strlen(zText)];
+ if( SQLITE_WITHIN(z,zText,zEnd) ){
+ db->errByteOffset = (int)(z-zText);
+ }
+}
+
+/*
+** If pExpr has a byte offset for the start of a token, record that as
+** as the error offset.
+*/
+SQLITE_PRIVATE void sqlcipher_sqlite3RecordErrorOffsetOfExpr(sqlcipher_sqlite3 *db, const Expr *pExpr){
+ while( pExpr
+ && (ExprHasProperty(pExpr,EP_OuterON|EP_InnerON) || pExpr->w.iOfst<=0)
+ ){
+ pExpr = pExpr->pLeft;
+ }
+ if( pExpr==0 ) return;
+ db->errByteOffset = pExpr->w.iOfst;
+}
+
/*
** Enlarge the memory allocation on a StrAccum object so that it is
** able to accept at least N more bytes of text.
@@ -34315,7 +30710,7 @@ SQLITE_API void sqlcipher_sqlite3_str_vappendf(
** Return the number of bytes of text that StrAccum is able to accept
** after the attempted enlargement. The value returned might be zero.
*/
-static int sqlcipher_sqlite3StrAccumEnlarge(StrAccum *p, int N){
+SQLITE_PRIVATE int sqlcipher_sqlite3StrAccumEnlarge(StrAccum *p, int N){
char *zNew;
assert( p->nChar+(i64)N >= p->nAlloc ); /* Only called if really needed */
if( p->accError ){
@@ -34324,12 +30719,12 @@ static int sqlcipher_sqlite3StrAccumEnlarge(StrAccum *p, int N){
return 0;
}
if( p->mxAlloc==0 ){
- setStrAccumError(p, SQLITE_TOOBIG);
+ sqlcipher_sqlite3StrAccumSetError(p, SQLITE_TOOBIG);
return p->nAlloc - p->nChar - 1;
}else{
char *zOld = isMalloced(p) ? p->zText : 0;
i64 szNew = p->nChar;
- szNew += N + 1;
+ szNew += (sqlcipher_sqlite3_int64)N + 1;
if( szNew+p->nChar<=p->mxAlloc ){
/* Force exponential buffer size growth as long as it does not overflow,
** to avoid having to call this routine too often */
@@ -34337,7 +30732,7 @@ static int sqlcipher_sqlite3StrAccumEnlarge(StrAccum *p, int N){
}
if( szNew > p->mxAlloc ){
sqlcipher_sqlite3_str_reset(p);
- setStrAccumError(p, SQLITE_TOOBIG);
+ sqlcipher_sqlite3StrAccumSetError(p, SQLITE_TOOBIG);
return 0;
}else{
p->nAlloc = (int)szNew;
@@ -34355,7 +30750,7 @@ static int sqlcipher_sqlite3StrAccumEnlarge(StrAccum *p, int N){
p->printfFlags |= SQLITE_PRINTF_MALLOCED;
}else{
sqlcipher_sqlite3_str_reset(p);
- setStrAccumError(p, SQLITE_NOMEM);
+ sqlcipher_sqlite3StrAccumSetError(p, SQLITE_NOMEM);
return 0;
}
}
@@ -34428,7 +30823,7 @@ static SQLITE_NOINLINE char *strAccumFinishRealloc(StrAccum *p){
memcpy(zText, p->zText, p->nChar+1);
p->printfFlags |= SQLITE_PRINTF_MALLOCED;
}else{
- setStrAccumError(p, SQLITE_NOMEM);
+ sqlcipher_sqlite3StrAccumSetError(p, SQLITE_NOMEM);
}
p->zText = zText;
return zText;
@@ -34444,6 +30839,22 @@ SQLITE_PRIVATE char *sqlcipher_sqlite3StrAccumFinish(StrAccum *p){
}
/*
+** Use the content of the StrAccum passed as the second argument
+** as the result of an SQL function.
+*/
+SQLITE_PRIVATE void sqlcipher_sqlite3ResultStrAccum(sqlcipher_sqlite3_context *pCtx, StrAccum *p){
+ if( p->accError ){
+ sqlcipher_sqlite3_result_error_code(pCtx, p->accError);
+ sqlcipher_sqlite3_str_reset(p);
+ }else if( isMalloced(p) ){
+ sqlcipher_sqlite3_result_text(pCtx, p->zText, p->nChar, SQLITE_DYNAMIC);
+ }else{
+ sqlcipher_sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC);
+ sqlcipher_sqlite3_str_reset(p);
+ }
+}
+
+/*
** This singleton is an sqlcipher_sqlite3_str object that is returned if
** sqlcipher_sqlite3_malloc() fails to provide space for a real one. This
** sqlcipher_sqlite3_str object accepts no new text and always returns
@@ -34745,40 +31156,44 @@ SQLITE_API void sqlcipher_sqlite3_str_appendf(StrAccum *p, const char *zFormat,
** Add a new subitem to the tree. The moreToFollow flag indicates that this
** is not the last item in the tree.
*/
-static TreeView *sqlcipher_sqlite3TreeViewPush(TreeView *p, u8 moreToFollow){
+static void sqlcipher_sqlite3TreeViewPush(TreeView **pp, u8 moreToFollow){
+ TreeView *p = *pp;
if( p==0 ){
- p = sqlcipher_sqlite3_malloc64( sizeof(*p) );
- if( p==0 ) return 0;
+ *pp = p = sqlcipher_sqlite3_malloc64( sizeof(*p) );
+ if( p==0 ) return;
memset(p, 0, sizeof(*p));
}else{
p->iLevel++;
}
assert( moreToFollow==0 || moreToFollow==1 );
- if( p->iLevel<sizeof(p->bLine) ) p->bLine[p->iLevel] = moreToFollow;
- return p;
+ if( p->iLevel<(int)sizeof(p->bLine) ) p->bLine[p->iLevel] = moreToFollow;
}
/*
** Finished with one layer of the tree
*/
-static void sqlcipher_sqlite3TreeViewPop(TreeView *p){
+static void sqlcipher_sqlite3TreeViewPop(TreeView **pp){
+ TreeView *p = *pp;
if( p==0 ) return;
p->iLevel--;
- if( p->iLevel<0 ) sqlcipher_sqlite3_free(p);
+ if( p->iLevel<0 ){
+ sqlcipher_sqlite3_free(p);
+ *pp = 0;
+ }
}
/*
** Generate a single line of output for the tree, with a prefix that contains
** all the appropriate tree lines
*/
-static void sqlcipher_sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){
+SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){
va_list ap;
int i;
StrAccum acc;
- char zBuf[500];
+ char zBuf[1000];
sqlcipher_sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
if( p ){
- for(i=0; i<p->iLevel && i<sizeof(p->bLine)-1; i++){
+ for(i=0; i<p->iLevel && i<(int)sizeof(p->bLine)-1; i++){
sqlcipher_sqlite3_str_append(&acc, p->bLine[i] ? "| " : " ", 4);
}
sqlcipher_sqlite3_str_append(&acc, p->bLine[i] ? "|-- " : "'-- ", 4);
@@ -34799,11 +31214,58 @@ static void sqlcipher_sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...)
** Shorthand for starting a new tree item that consists of a single label
*/
static void sqlcipher_sqlite3TreeViewItem(TreeView *p, const char *zLabel,u8 moreFollows){
- p = sqlcipher_sqlite3TreeViewPush(p, moreFollows);
+ sqlcipher_sqlite3TreeViewPush(&p, moreFollows);
sqlcipher_sqlite3TreeViewLine(p, "%s", zLabel);
}
/*
+** Show a list of Column objects in tree format.
+*/
+SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewColumnList(
+ TreeView *pView,
+ const Column *aCol,
+ int nCol,
+ u8 moreToFollow
+){
+ int i;
+ sqlcipher_sqlite3TreeViewPush(&pView, moreToFollow);
+ sqlcipher_sqlite3TreeViewLine(pView, "COLUMNS");
+ for(i=0; i<nCol; i++){
+ u16 flg = aCol[i].colFlags;
+ int colMoreToFollow = i<(nCol - 1);
+ sqlcipher_sqlite3TreeViewPush(&pView, colMoreToFollow);
+ sqlcipher_sqlite3TreeViewLine(pView, 0);
+ printf(" %s", aCol[i].zCnName);
+ switch( aCol[i].eCType ){
+ case COLTYPE_ANY: printf(" ANY"); break;
+ case COLTYPE_BLOB: printf(" BLOB"); break;
+ case COLTYPE_INT: printf(" INT"); break;
+ case COLTYPE_INTEGER: printf(" INTEGER"); break;
+ case COLTYPE_REAL: printf(" REAL"); break;
+ case COLTYPE_TEXT: printf(" TEXT"); break;
+ case COLTYPE_CUSTOM: {
+ if( flg & COLFLAG_HASTYPE ){
+ const char *z = aCol[i].zCnName;
+ z += strlen(z)+1;
+ printf(" X-%s", z);
+ break;
+ }
+ }
+ }
+ if( flg & COLFLAG_PRIMKEY ) printf(" PRIMARY KEY");
+ if( flg & COLFLAG_HIDDEN ) printf(" HIDDEN");
+#ifdef COLFLAG_NOEXPAND
+ if( flg & COLFLAG_NOEXPAND ) printf(" NO-EXPAND");
+#endif
+ if( flg ) printf(" flags=%04x", flg);
+ printf("\n");
+ fflush(stdout);
+ sqlcipher_sqlite3TreeViewPop(&pView);
+ }
+ sqlcipher_sqlite3TreeViewPop(&pView);
+}
+
+/*
** Generate a human-readable description of a WITH clause.
*/
SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewWith(TreeView *pView, const With *pWith, u8 moreToFollow){
@@ -34816,7 +31278,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewWith(TreeView *pView, const With *p
sqlcipher_sqlite3TreeViewLine(pView, "WITH (0x%p)", pWith);
}
if( pWith->nCte>0 ){
- pView = sqlcipher_sqlite3TreeViewPush(pView, 1);
+ sqlcipher_sqlite3TreeViewPush(&pView, moreToFollow);
for(i=0; i<pWith->nCte; i++){
StrAccum x;
char zLine[1000];
@@ -34832,13 +31294,20 @@ SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewWith(TreeView *pView, const With *p
}
sqlcipher_sqlite3_str_appendf(&x, ")");
}
- sqlcipher_sqlite3_str_appendf(&x, " AS");
+ if( pCte->eM10d!=M10d_Any ){
+ sqlcipher_sqlite3_str_appendf(&x, " %sMATERIALIZED",
+ pCte->eM10d==M10d_No ? "NOT " : "");
+ }
+ if( pCte->pUse ){
+ sqlcipher_sqlite3_str_appendf(&x, " (pUse=0x%p, nUse=%d)", pCte->pUse,
+ pCte->pUse->nUse);
+ }
sqlcipher_sqlite3StrAccumFinish(&x);
sqlcipher_sqlite3TreeViewItem(pView, zLine, i<pWith->nCte-1);
sqlcipher_sqlite3TreeViewSelect(pView, pCte->pSelect, 0);
- sqlcipher_sqlite3TreeViewPop(pView);
+ sqlcipher_sqlite3TreeViewPop(&pView);
}
- sqlcipher_sqlite3TreeViewPop(pView);
+ sqlcipher_sqlite3TreeViewPop(&pView);
}
}
@@ -34847,39 +31316,61 @@ SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewWith(TreeView *pView, const With *p
*/
SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc){
int i;
+ if( pSrc==0 ) return;
for(i=0; i<pSrc->nSrc; i++){
- const struct SrcList_item *pItem = &pSrc->a[i];
+ const SrcItem *pItem = &pSrc->a[i];
StrAccum x;
- char zLine[100];
+ int n = 0;
+ char zLine[1000];
sqlcipher_sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
- sqlcipher_sqlite3_str_appendf(&x, "{%d:*}", pItem->iCursor);
- if( pItem->zDatabase ){
- sqlcipher_sqlite3_str_appendf(&x, " %s.%s", pItem->zDatabase, pItem->zName);
- }else if( pItem->zName ){
- sqlcipher_sqlite3_str_appendf(&x, " %s", pItem->zName);
- }
+ x.printfFlags |= SQLITE_PRINTF_INTERNAL;
+ sqlcipher_sqlite3_str_appendf(&x, "{%d:*} %!S", pItem->iCursor, pItem);
if( pItem->pTab ){
sqlcipher_sqlite3_str_appendf(&x, " tab=%Q nCol=%d ptr=%p used=%llx",
pItem->pTab->zName, pItem->pTab->nCol, pItem->pTab, pItem->colUsed);
}
- if( pItem->zAlias ){
- sqlcipher_sqlite3_str_appendf(&x, " (AS %s)", pItem->zAlias);
- }
- if( pItem->fg.jointype & JT_LEFT ){
+ if( (pItem->fg.jointype & (JT_LEFT|JT_RIGHT))==(JT_LEFT|JT_RIGHT) ){
+ sqlcipher_sqlite3_str_appendf(&x, " FULL-OUTER-JOIN");
+ }else if( pItem->fg.jointype & JT_LEFT ){
sqlcipher_sqlite3_str_appendf(&x, " LEFT-JOIN");
+ }else if( pItem->fg.jointype & JT_RIGHT ){
+ sqlcipher_sqlite3_str_appendf(&x, " RIGHT-JOIN");
+ }else if( pItem->fg.jointype & JT_CROSS ){
+ sqlcipher_sqlite3_str_appendf(&x, " CROSS-JOIN");
+ }
+ if( pItem->fg.jointype & JT_LTORJ ){
+ sqlcipher_sqlite3_str_appendf(&x, " LTORJ");
}
if( pItem->fg.fromDDL ){
sqlcipher_sqlite3_str_appendf(&x, " DDL");
}
+ if( pItem->fg.isCte ){
+ sqlcipher_sqlite3_str_appendf(&x, " CteUse=0x%p", pItem->u2.pCteUse);
+ }
+ if( pItem->fg.isOn || (pItem->fg.isUsing==0 && pItem->u3.pOn!=0) ){
+ sqlcipher_sqlite3_str_appendf(&x, " ON");
+ }
sqlcipher_sqlite3StrAccumFinish(&x);
sqlcipher_sqlite3TreeViewItem(pView, zLine, i<pSrc->nSrc-1);
+ n = 0;
+ if( pItem->pSelect ) n++;
+ if( pItem->fg.isTabFunc ) n++;
+ if( pItem->fg.isUsing ) n++;
+ if( pItem->fg.isUsing ){
+ sqlcipher_sqlite3TreeViewIdList(pView, pItem->u3.pUsing, (--n)>0, "USING");
+ }
if( pItem->pSelect ){
- sqlcipher_sqlite3TreeViewSelect(pView, pItem->pSelect, 0);
+ if( pItem->pTab ){
+ Table *pTab = pItem->pTab;
+ sqlcipher_sqlite3TreeViewColumnList(pView, pTab->aCol, pTab->nCol, 1);
+ }
+ assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem->pSelect) );
+ sqlcipher_sqlite3TreeViewSelect(pView, pItem->pSelect, (--n)>0);
}
if( pItem->fg.isTabFunc ){
sqlcipher_sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:");
}
- sqlcipher_sqlite3TreeViewPop(pView);
+ sqlcipher_sqlite3TreeViewPop(&pView);
}
}
@@ -34893,11 +31384,11 @@ SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewSelect(TreeView *pView, const Selec
sqlcipher_sqlite3TreeViewLine(pView, "nil-SELECT");
return;
}
- pView = sqlcipher_sqlite3TreeViewPush(pView, moreToFollow);
+ sqlcipher_sqlite3TreeViewPush(&pView, moreToFollow);
if( p->pWith ){
sqlcipher_sqlite3TreeViewWith(pView, p->pWith, 1);
cnt = 1;
- sqlcipher_sqlite3TreeViewPush(pView, 1);
+ sqlcipher_sqlite3TreeViewPush(&pView, 1);
}
do{
if( p->selFlags & SF_WhereBegin ){
@@ -34911,7 +31402,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewSelect(TreeView *pView, const Selec
(int)p->nSelectRow
);
}
- if( cnt++ ) sqlcipher_sqlite3TreeViewPop(pView);
+ if( cnt++ ) sqlcipher_sqlite3TreeViewPop(&pView);
if( p->pPrior ){
n = 1000;
}else{
@@ -34934,24 +31425,24 @@ SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewSelect(TreeView *pView, const Selec
#ifndef SQLITE_OMIT_WINDOWFUNC
if( p->pWin ){
Window *pX;
- pView = sqlcipher_sqlite3TreeViewPush(pView, (n--)>0);
+ sqlcipher_sqlite3TreeViewPush(&pView, (n--)>0);
sqlcipher_sqlite3TreeViewLine(pView, "window-functions");
for(pX=p->pWin; pX; pX=pX->pNextWin){
sqlcipher_sqlite3TreeViewWinFunc(pView, pX, pX->pNextWin!=0);
}
- sqlcipher_sqlite3TreeViewPop(pView);
+ sqlcipher_sqlite3TreeViewPop(&pView);
}
#endif
if( p->pSrc && p->pSrc->nSrc ){
- pView = sqlcipher_sqlite3TreeViewPush(pView, (n--)>0);
+ sqlcipher_sqlite3TreeViewPush(&pView, (n--)>0);
sqlcipher_sqlite3TreeViewLine(pView, "FROM");
sqlcipher_sqlite3TreeViewSrcList(pView, p->pSrc);
- sqlcipher_sqlite3TreeViewPop(pView);
+ sqlcipher_sqlite3TreeViewPop(&pView);
}
if( p->pWhere ){
sqlcipher_sqlite3TreeViewItem(pView, "WHERE", (n--)>0);
sqlcipher_sqlite3TreeViewExpr(pView, p->pWhere, 0);
- sqlcipher_sqlite3TreeViewPop(pView);
+ sqlcipher_sqlite3TreeViewPop(&pView);
}
if( p->pGroupBy ){
sqlcipher_sqlite3TreeViewExprList(pView, p->pGroupBy, (n--)>0, "GROUPBY");
@@ -34959,7 +31450,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewSelect(TreeView *pView, const Selec
if( p->pHaving ){
sqlcipher_sqlite3TreeViewItem(pView, "HAVING", (n--)>0);
sqlcipher_sqlite3TreeViewExpr(pView, p->pHaving, 0);
- sqlcipher_sqlite3TreeViewPop(pView);
+ sqlcipher_sqlite3TreeViewPop(&pView);
}
#ifndef SQLITE_OMIT_WINDOWFUNC
if( p->pWinDefn ){
@@ -34968,7 +31459,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewSelect(TreeView *pView, const Selec
for(pX=p->pWinDefn; pX; pX=pX->pNextWin){
sqlcipher_sqlite3TreeViewWindow(pView, pX, pX->pNextWin!=0);
}
- sqlcipher_sqlite3TreeViewPop(pView);
+ sqlcipher_sqlite3TreeViewPop(&pView);
}
#endif
if( p->pOrderBy ){
@@ -34980,9 +31471,9 @@ SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewSelect(TreeView *pView, const Selec
if( p->pLimit->pRight ){
sqlcipher_sqlite3TreeViewItem(pView, "OFFSET", (n--)>0);
sqlcipher_sqlite3TreeViewExpr(pView, p->pLimit->pRight, 0);
- sqlcipher_sqlite3TreeViewPop(pView);
+ sqlcipher_sqlite3TreeViewPop(&pView);
}
- sqlcipher_sqlite3TreeViewPop(pView);
+ sqlcipher_sqlite3TreeViewPop(&pView);
}
if( p->pPrior ){
const char *zOp = "UNION";
@@ -34995,7 +31486,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewSelect(TreeView *pView, const Selec
}
p = p->pPrior;
}while( p!=0 );
- sqlcipher_sqlite3TreeViewPop(pView);
+ sqlcipher_sqlite3TreeViewPop(&pView);
}
#ifndef SQLITE_OMIT_WINDOWFUNC
@@ -35011,24 +31502,24 @@ SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewBound(
switch( eBound ){
case TK_UNBOUNDED: {
sqlcipher_sqlite3TreeViewItem(pView, "UNBOUNDED", moreToFollow);
- sqlcipher_sqlite3TreeViewPop(pView);
+ sqlcipher_sqlite3TreeViewPop(&pView);
break;
}
case TK_CURRENT: {
sqlcipher_sqlite3TreeViewItem(pView, "CURRENT", moreToFollow);
- sqlcipher_sqlite3TreeViewPop(pView);
+ sqlcipher_sqlite3TreeViewPop(&pView);
break;
}
case TK_PRECEDING: {
sqlcipher_sqlite3TreeViewItem(pView, "PRECEDING", moreToFollow);
sqlcipher_sqlite3TreeViewExpr(pView, pExpr, 0);
- sqlcipher_sqlite3TreeViewPop(pView);
+ sqlcipher_sqlite3TreeViewPop(&pView);
break;
}
case TK_FOLLOWING: {
sqlcipher_sqlite3TreeViewItem(pView, "FOLLOWING", moreToFollow);
sqlcipher_sqlite3TreeViewExpr(pView, pExpr, 0);
- sqlcipher_sqlite3TreeViewPop(pView);
+ sqlcipher_sqlite3TreeViewPop(&pView);
break;
}
}
@@ -35041,12 +31532,13 @@ SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewBound(
*/
SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewWindow(TreeView *pView, const Window *pWin, u8 more){
int nElement = 0;
+ if( pWin==0 ) return;
if( pWin->pFilter ){
sqlcipher_sqlite3TreeViewItem(pView, "FILTER", 1);
sqlcipher_sqlite3TreeViewExpr(pView, pWin->pFilter, 0);
- sqlcipher_sqlite3TreeViewPop(pView);
+ sqlcipher_sqlite3TreeViewPop(&pView);
}
- pView = sqlcipher_sqlite3TreeViewPush(pView, more);
+ sqlcipher_sqlite3TreeViewPush(&pView, more);
if( pWin->zName ){
sqlcipher_sqlite3TreeViewLine(pView, "OVER %s (%p)", pWin->zName, pWin);
}else{
@@ -35057,9 +31549,9 @@ SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewWindow(TreeView *pView, const Windo
if( pWin->eFrmType ) nElement++;
if( pWin->eExclude ) nElement++;
if( pWin->zBase ){
- sqlcipher_sqlite3TreeViewPush(pView, (--nElement)>0);
+ sqlcipher_sqlite3TreeViewPush(&pView, (--nElement)>0);
sqlcipher_sqlite3TreeViewLine(pView, "window: %s", pWin->zBase);
- sqlcipher_sqlite3TreeViewPop(pView);
+ sqlcipher_sqlite3TreeViewPop(&pView);
}
if( pWin->pPartition ){
sqlcipher_sqlite3TreeViewExprList(pView, pWin->pPartition, nElement>0,"PARTITION-BY");
@@ -35077,7 +31569,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewWindow(TreeView *pView, const Windo
sqlcipher_sqlite3TreeViewItem(pView, zBuf, (--nElement)>0);
sqlcipher_sqlite3TreeViewBound(pView, pWin->eStart, pWin->pStart, 1);
sqlcipher_sqlite3TreeViewBound(pView, pWin->eEnd, pWin->pEnd, 0);
- sqlcipher_sqlite3TreeViewPop(pView);
+ sqlcipher_sqlite3TreeViewPop(&pView);
}
if( pWin->eExclude ){
char zBuf[30];
@@ -35092,11 +31584,11 @@ SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewWindow(TreeView *pView, const Windo
zExclude = zBuf;
break;
}
- sqlcipher_sqlite3TreeViewPush(pView, 0);
+ sqlcipher_sqlite3TreeViewPush(&pView, 0);
sqlcipher_sqlite3TreeViewLine(pView, "EXCLUDE %s", zExclude);
- sqlcipher_sqlite3TreeViewPop(pView);
+ sqlcipher_sqlite3TreeViewPop(&pView);
}
- sqlcipher_sqlite3TreeViewPop(pView);
+ sqlcipher_sqlite3TreeViewPop(&pView);
}
#endif /* SQLITE_OMIT_WINDOWFUNC */
@@ -35105,11 +31597,12 @@ SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewWindow(TreeView *pView, const Windo
** Generate a human-readable explanation for a Window Function object
*/
SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewWinFunc(TreeView *pView, const Window *pWin, u8 more){
- pView = sqlcipher_sqlite3TreeViewPush(pView, more);
+ if( pWin==0 ) return;
+ sqlcipher_sqlite3TreeViewPush(&pView, more);
sqlcipher_sqlite3TreeViewLine(pView, "WINFUNC %s(%d)",
- pWin->pFunc->zName, pWin->pFunc->nArg);
+ pWin->pWFunc->zName, pWin->pWFunc->nArg);
sqlcipher_sqlite3TreeViewWindow(pView, pWin, 0);
- sqlcipher_sqlite3TreeViewPop(pView);
+ sqlcipher_sqlite3TreeViewPop(&pView);
}
#endif /* SQLITE_OMIT_WINDOWFUNC */
@@ -35120,10 +31613,10 @@ SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewExpr(TreeView *pView, const Expr *p
const char *zBinOp = 0; /* Binary operator */
const char *zUniOp = 0; /* Unary operator */
char zFlgs[200];
- pView = sqlcipher_sqlite3TreeViewPush(pView, moreToFollow);
+ sqlcipher_sqlite3TreeViewPush(&pView, moreToFollow);
if( pExpr==0 ){
sqlcipher_sqlite3TreeViewLine(pView, "nil");
- sqlcipher_sqlite3TreeViewPop(pView);
+ sqlcipher_sqlite3TreeViewPop(&pView);
return;
}
if( pExpr->flags || pExpr->affExpr || pExpr->vvaFlags ){
@@ -35131,8 +31624,11 @@ SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewExpr(TreeView *pView, const Expr *p
sqlcipher_sqlite3StrAccumInit(&x, 0, zFlgs, sizeof(zFlgs), 0);
sqlcipher_sqlite3_str_appendf(&x, " fg.af=%x.%c",
pExpr->flags, pExpr->affExpr ? pExpr->affExpr : 'n');
- if( ExprHasProperty(pExpr, EP_FromJoin) ){
- sqlcipher_sqlite3_str_appendf(&x, " iRJT=%d", pExpr->iRightJoinTable);
+ if( ExprHasProperty(pExpr, EP_OuterON) ){
+ sqlcipher_sqlite3_str_appendf(&x, " outer.iJoin=%d", pExpr->w.iJoin);
+ }
+ if( ExprHasProperty(pExpr, EP_InnerON) ){
+ sqlcipher_sqlite3_str_appendf(&x, " inner.iJoin=%d", pExpr->w.iJoin);
}
if( ExprHasProperty(pExpr, EP_FromDDL) ){
sqlcipher_sqlite3_str_appendf(&x, " DDL");
@@ -35162,6 +31658,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewExpr(TreeView *pView, const Expr *p
sqlcipher_sqlite3TreeViewLine(pView, "COLUMN(%d)%s%s",
pExpr->iColumn, zFlgs, zOp2);
}else{
+ assert( ExprUseYTab(pExpr) );
sqlcipher_sqlite3TreeViewLine(pView, "{%d:%d} pTab=%p%s",
pExpr->iTable, pExpr->iColumn,
pExpr->y.pTab, zFlgs);
@@ -35181,11 +31678,13 @@ SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewExpr(TreeView *pView, const Expr *p
}
#ifndef SQLITE_OMIT_FLOATING_POINT
case TK_FLOAT: {
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
sqlcipher_sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);
break;
}
#endif
case TK_STRING: {
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
sqlcipher_sqlite3TreeViewLine(pView,"%Q", pExpr->u.zToken);
break;
}
@@ -35194,17 +31693,19 @@ SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewExpr(TreeView *pView, const Expr *p
break;
}
case TK_TRUEFALSE: {
- sqlcipher_sqlite3TreeViewLine(pView,
- sqlcipher_sqlite3ExprTruthValue(pExpr) ? "TRUE" : "FALSE");
+ sqlcipher_sqlite3TreeViewLine(pView,"%s%s",
+ sqlcipher_sqlite3ExprTruthValue(pExpr) ? "TRUE" : "FALSE", zFlgs);
break;
}
#ifndef SQLITE_OMIT_BLOB_LITERAL
case TK_BLOB: {
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
sqlcipher_sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);
break;
}
#endif
case TK_VARIABLE: {
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
sqlcipher_sqlite3TreeViewLine(pView,"VARIABLE(%s,%d)",
pExpr->u.zToken, pExpr->iColumn);
break;
@@ -35214,12 +31715,14 @@ SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewExpr(TreeView *pView, const Expr *p
break;
}
case TK_ID: {
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
sqlcipher_sqlite3TreeViewLine(pView,"ID \"%w\"", pExpr->u.zToken);
break;
}
#ifndef SQLITE_OMIT_CAST
case TK_CAST: {
/* Expressions of the form: CAST(pLeft AS token) */
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
sqlcipher_sqlite3TreeViewLine(pView,"CAST %Q", pExpr->u.zToken);
sqlcipher_sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
break;
@@ -35269,6 +31772,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewExpr(TreeView *pView, const Expr *p
}
case TK_SPAN: {
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
sqlcipher_sqlite3TreeViewLine(pView, "SPAN %Q", pExpr->u.zToken);
sqlcipher_sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
break;
@@ -35280,6 +31784,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewExpr(TreeView *pView, const Expr *p
** up in the treeview output as "SOFT-COLLATE". Explicit COLLATE
** operators that appear in the original SQL always have the
** EP_Collate bit set and appear in treeview output as just "COLLATE" */
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
sqlcipher_sqlite3TreeViewLine(pView, "%sCOLLATE %Q%s",
!ExprHasProperty(pExpr, EP_Collate) ? "SOFT-" : "",
pExpr->u.zToken, zFlgs);
@@ -35295,6 +31800,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewExpr(TreeView *pView, const Expr *p
pFarg = 0;
pWin = 0;
}else{
+ assert( ExprUseXList(pExpr) );
pFarg = pExpr->x.pList;
#ifndef SQLITE_OMIT_WINDOWFUNC
pWin = ExprHasProperty(pExpr, EP_WinFunc) ? pExpr->y.pWin : 0;
@@ -35302,6 +31808,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewExpr(TreeView *pView, const Expr *p
pWin = 0;
#endif
}
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
if( pExpr->op==TK_AGG_FUNCTION ){
sqlcipher_sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q%s agg=%d[%d]/%p",
pExpr->op2, pExpr->u.zToken, zFlgs,
@@ -35333,19 +31840,31 @@ SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewExpr(TreeView *pView, const Expr *p
}
#ifndef SQLITE_OMIT_SUBQUERY
case TK_EXISTS: {
+ assert( ExprUseXSelect(pExpr) );
sqlcipher_sqlite3TreeViewLine(pView, "EXISTS-expr flags=0x%x", pExpr->flags);
sqlcipher_sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
break;
}
case TK_SELECT: {
+ assert( ExprUseXSelect(pExpr) );
sqlcipher_sqlite3TreeViewLine(pView, "subquery-expr flags=0x%x", pExpr->flags);
sqlcipher_sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
break;
}
case TK_IN: {
- sqlcipher_sqlite3TreeViewLine(pView, "IN flags=0x%x", pExpr->flags);
+ sqlcipher_sqlite3_str *pStr = sqlcipher_sqlite3_str_new(0);
+ char *z;
+ sqlcipher_sqlite3_str_appendf(pStr, "IN flags=0x%x", pExpr->flags);
+ if( pExpr->iTable ) sqlcipher_sqlite3_str_appendf(pStr, " iTable=%d",pExpr->iTable);
+ if( ExprHasProperty(pExpr, EP_Subrtn) ){
+ sqlcipher_sqlite3_str_appendf(pStr, " subrtn(%d,%d)",
+ pExpr->y.sub.regReturn, pExpr->y.sub.iAddr);
+ }
+ z = sqlcipher_sqlite3_str_finish(pStr);
+ sqlcipher_sqlite3TreeViewLine(pView, z);
+ sqlcipher_sqlite3_free(z);
sqlcipher_sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
- if( ExprHasProperty(pExpr, EP_xIsSelect) ){
+ if( ExprUseXSelect(pExpr) ){
sqlcipher_sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
}else{
sqlcipher_sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);
@@ -35366,9 +31885,12 @@ SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewExpr(TreeView *pView, const Expr *p
** Z is stored in pExpr->pList->a[1].pExpr.
*/
case TK_BETWEEN: {
- Expr *pX = pExpr->pLeft;
- Expr *pY = pExpr->x.pList->a[0].pExpr;
- Expr *pZ = pExpr->x.pList->a[1].pExpr;
+ const Expr *pX, *pY, *pZ;
+ pX = pExpr->pLeft;
+ assert( ExprUseXList(pExpr) );
+ assert( pExpr->x.pList->nExpr==2 );
+ pY = pExpr->x.pList->a[0].pExpr;
+ pZ = pExpr->x.pList->a[1].pExpr;
sqlcipher_sqlite3TreeViewLine(pView, "BETWEEN");
sqlcipher_sqlite3TreeViewExpr(pView, pX, 1);
sqlcipher_sqlite3TreeViewExpr(pView, pY, 1);
@@ -35390,6 +31912,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewExpr(TreeView *pView, const Expr *p
case TK_CASE: {
sqlcipher_sqlite3TreeViewLine(pView, "CASE");
sqlcipher_sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
+ assert( ExprUseXList(pExpr) );
sqlcipher_sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);
break;
}
@@ -35402,6 +31925,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewExpr(TreeView *pView, const Expr *p
case OE_Fail: zType = "fail"; break;
case OE_Ignore: zType = "ignore"; break;
}
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
sqlcipher_sqlite3TreeViewLine(pView, "RAISE %s(%Q)", zType, pExpr->u.zToken);
break;
}
@@ -35414,12 +31938,16 @@ SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewExpr(TreeView *pView, const Expr *p
}
case TK_VECTOR: {
char *z = sqlcipher_sqlite3_mprintf("VECTOR%s",zFlgs);
+ assert( ExprUseXList(pExpr) );
sqlcipher_sqlite3TreeViewBareExprList(pView, pExpr->x.pList, z);
sqlcipher_sqlite3_free(z);
break;
}
case TK_SELECT_COLUMN: {
- sqlcipher_sqlite3TreeViewLine(pView, "SELECT-COLUMN %d", pExpr->iColumn);
+ sqlcipher_sqlite3TreeViewLine(pView, "SELECT-COLUMN %d of [0..%d]%s",
+ pExpr->iColumn, pExpr->iTable-1,
+ pExpr->pRight==pExpr->pLeft ? " (SELECT-owner)" : "");
+ assert( ExprUseXSelect(pExpr->pLeft) );
sqlcipher_sqlite3TreeViewSelect(pView, pExpr->pLeft->x.pSelect, 0);
break;
}
@@ -35428,6 +31956,23 @@ SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewExpr(TreeView *pView, const Expr *p
sqlcipher_sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
break;
}
+ case TK_ERROR: {
+ Expr tmp;
+ sqlcipher_sqlite3TreeViewLine(pView, "ERROR");
+ tmp = *pExpr;
+ tmp.op = pExpr->op2;
+ sqlcipher_sqlite3TreeViewExpr(pView, &tmp, 0);
+ break;
+ }
+ case TK_ROW: {
+ if( pExpr->iColumn<=0 ){
+ sqlcipher_sqlite3TreeViewLine(pView, "First FROM table rowid");
+ }else{
+ sqlcipher_sqlite3TreeViewLine(pView, "First FROM table column %d",
+ pExpr->iColumn-1);
+ }
+ break;
+ }
default: {
sqlcipher_sqlite3TreeViewLine(pView, "op=%d", pExpr->op);
break;
@@ -35441,7 +31986,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewExpr(TreeView *pView, const Expr *p
sqlcipher_sqlite3TreeViewLine(pView, "%s%s", zUniOp, zFlgs);
sqlcipher_sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
}
- sqlcipher_sqlite3TreeViewPop(pView);
+ sqlcipher_sqlite3TreeViewPop(&pView);
}
@@ -35463,13 +32008,25 @@ SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewBareExprList(
int j = pList->a[i].u.x.iOrderByCol;
char *zName = pList->a[i].zEName;
int moreToFollow = i<pList->nExpr - 1;
- if( pList->a[i].eEName!=ENAME_NAME ) zName = 0;
if( j || zName ){
- sqlcipher_sqlite3TreeViewPush(pView, moreToFollow);
+ sqlcipher_sqlite3TreeViewPush(&pView, moreToFollow);
moreToFollow = 0;
sqlcipher_sqlite3TreeViewLine(pView, 0);
if( zName ){
- fprintf(stdout, "AS %s ", zName);
+ switch( pList->a[i].fg.eEName ){
+ default:
+ fprintf(stdout, "AS %s ", zName);
+ break;
+ case ENAME_TAB:
+ fprintf(stdout, "TABLE-ALIAS-NAME(\"%s\") ", zName);
+ if( pList->a[i].fg.bUsed ) fprintf(stdout, "(used) ");
+ if( pList->a[i].fg.bUsingTerm ) fprintf(stdout, "(USING-term) ");
+ if( pList->a[i].fg.bNoExpand ) fprintf(stdout, "(NoExpand) ");
+ break;
+ case ENAME_SPAN:
+ fprintf(stdout, "SPAN(\"%s\") ", zName);
+ break;
+ }
}
if( j ){
fprintf(stdout, "iOrderByCol=%d", j);
@@ -35479,7 +32036,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewBareExprList(
}
sqlcipher_sqlite3TreeViewExpr(pView, pList->a[i].pExpr, moreToFollow);
if( j || zName ){
- sqlcipher_sqlite3TreeViewPop(pView);
+ sqlcipher_sqlite3TreeViewPop(&pView);
}
}
}
@@ -35490,10 +32047,377 @@ SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewExprList(
u8 moreToFollow,
const char *zLabel
){
- pView = sqlcipher_sqlite3TreeViewPush(pView, moreToFollow);
+ sqlcipher_sqlite3TreeViewPush(&pView, moreToFollow);
sqlcipher_sqlite3TreeViewBareExprList(pView, pList, zLabel);
- sqlcipher_sqlite3TreeViewPop(pView);
+ sqlcipher_sqlite3TreeViewPop(&pView);
+}
+
+/*
+** Generate a human-readable explanation of an id-list.
+*/
+SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewBareIdList(
+ TreeView *pView,
+ const IdList *pList,
+ const char *zLabel
+){
+ if( zLabel==0 || zLabel[0]==0 ) zLabel = "LIST";
+ if( pList==0 ){
+ sqlcipher_sqlite3TreeViewLine(pView, "%s (empty)", zLabel);
+ }else{
+ int i;
+ sqlcipher_sqlite3TreeViewLine(pView, "%s", zLabel);
+ for(i=0; i<pList->nId; i++){
+ char *zName = pList->a[i].zName;
+ int moreToFollow = i<pList->nId - 1;
+ if( zName==0 ) zName = "(null)";
+ sqlcipher_sqlite3TreeViewPush(&pView, moreToFollow);
+ sqlcipher_sqlite3TreeViewLine(pView, 0);
+ if( pList->eU4==EU4_NONE ){
+ fprintf(stdout, "%s\n", zName);
+ }else if( pList->eU4==EU4_IDX ){
+ fprintf(stdout, "%s (%d)\n", zName, pList->a[i].u4.idx);
+ }else{
+ assert( pList->eU4==EU4_EXPR );
+ if( pList->a[i].u4.pExpr==0 ){
+ fprintf(stdout, "%s (pExpr=NULL)\n", zName);
+ }else{
+ fprintf(stdout, "%s\n", zName);
+ sqlcipher_sqlite3TreeViewPush(&pView, i<pList->nId-1);
+ sqlcipher_sqlite3TreeViewExpr(pView, pList->a[i].u4.pExpr, 0);
+ sqlcipher_sqlite3TreeViewPop(&pView);
+ }
+ }
+ sqlcipher_sqlite3TreeViewPop(&pView);
+ }
+ }
+}
+SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewIdList(
+ TreeView *pView,
+ const IdList *pList,
+ u8 moreToFollow,
+ const char *zLabel
+){
+ sqlcipher_sqlite3TreeViewPush(&pView, moreToFollow);
+ sqlcipher_sqlite3TreeViewBareIdList(pView, pList, zLabel);
+ sqlcipher_sqlite3TreeViewPop(&pView);
+}
+
+/*
+** Generate a human-readable explanation of a list of Upsert objects
+*/
+SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewUpsert(
+ TreeView *pView,
+ const Upsert *pUpsert,
+ u8 moreToFollow
+){
+ if( pUpsert==0 ) return;
+ sqlcipher_sqlite3TreeViewPush(&pView, moreToFollow);
+ while( pUpsert ){
+ int n;
+ sqlcipher_sqlite3TreeViewPush(&pView, pUpsert->pNextUpsert!=0 || moreToFollow);
+ sqlcipher_sqlite3TreeViewLine(pView, "ON CONFLICT DO %s",
+ pUpsert->isDoUpdate ? "UPDATE" : "NOTHING");
+ n = (pUpsert->pUpsertSet!=0) + (pUpsert->pUpsertWhere!=0);
+ sqlcipher_sqlite3TreeViewExprList(pView, pUpsert->pUpsertTarget, (n--)>0, "TARGET");
+ sqlcipher_sqlite3TreeViewExprList(pView, pUpsert->pUpsertSet, (n--)>0, "SET");
+ if( pUpsert->pUpsertWhere ){
+ sqlcipher_sqlite3TreeViewItem(pView, "WHERE", (n--)>0);
+ sqlcipher_sqlite3TreeViewExpr(pView, pUpsert->pUpsertWhere, 0);
+ sqlcipher_sqlite3TreeViewPop(&pView);
+ }
+ sqlcipher_sqlite3TreeViewPop(&pView);
+ pUpsert = pUpsert->pNextUpsert;
+ }
+ sqlcipher_sqlite3TreeViewPop(&pView);
+}
+
+#if TREETRACE_ENABLED
+/*
+** Generate a human-readable diagram of the data structure that go
+** into generating an DELETE statement.
+*/
+SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewDelete(
+ const With *pWith,
+ const SrcList *pTabList,
+ const Expr *pWhere,
+ const ExprList *pOrderBy,
+ const Expr *pLimit,
+ const Trigger *pTrigger
+){
+ int n = 0;
+ TreeView *pView = 0;
+ sqlcipher_sqlite3TreeViewPush(&pView, 0);
+ sqlcipher_sqlite3TreeViewLine(pView, "DELETE");
+ if( pWith ) n++;
+ if( pTabList ) n++;
+ if( pWhere ) n++;
+ if( pOrderBy ) n++;
+ if( pLimit ) n++;
+ if( pTrigger ) n++;
+ if( pWith ){
+ sqlcipher_sqlite3TreeViewPush(&pView, (--n)>0);
+ sqlcipher_sqlite3TreeViewWith(pView, pWith, 0);
+ sqlcipher_sqlite3TreeViewPop(&pView);
+ }
+ if( pTabList ){
+ sqlcipher_sqlite3TreeViewPush(&pView, (--n)>0);
+ sqlcipher_sqlite3TreeViewLine(pView, "FROM");
+ sqlcipher_sqlite3TreeViewSrcList(pView, pTabList);
+ sqlcipher_sqlite3TreeViewPop(&pView);
+ }
+ if( pWhere ){
+ sqlcipher_sqlite3TreeViewPush(&pView, (--n)>0);
+ sqlcipher_sqlite3TreeViewLine(pView, "WHERE");
+ sqlcipher_sqlite3TreeViewExpr(pView, pWhere, 0);
+ sqlcipher_sqlite3TreeViewPop(&pView);
+ }
+ if( pOrderBy ){
+ sqlcipher_sqlite3TreeViewExprList(pView, pOrderBy, (--n)>0, "ORDER-BY");
+ }
+ if( pLimit ){
+ sqlcipher_sqlite3TreeViewPush(&pView, (--n)>0);
+ sqlcipher_sqlite3TreeViewLine(pView, "LIMIT");
+ sqlcipher_sqlite3TreeViewExpr(pView, pLimit, 0);
+ sqlcipher_sqlite3TreeViewPop(&pView);
+ }
+ if( pTrigger ){
+ sqlcipher_sqlite3TreeViewTrigger(pView, pTrigger, (--n)>0, 1);
+ }
+ sqlcipher_sqlite3TreeViewPop(&pView);
+}
+#endif /* TREETRACE_ENABLED */
+
+#if TREETRACE_ENABLED
+/*
+** Generate a human-readable diagram of the data structure that go
+** into generating an INSERT statement.
+*/
+SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewInsert(
+ const With *pWith,
+ const SrcList *pTabList,
+ const IdList *pColumnList,
+ const Select *pSelect,
+ const ExprList *pExprList,
+ int onError,
+ const Upsert *pUpsert,
+ const Trigger *pTrigger
+){
+ TreeView *pView = 0;
+ int n = 0;
+ const char *zLabel = "INSERT";
+ switch( onError ){
+ case OE_Replace: zLabel = "REPLACE"; break;
+ case OE_Ignore: zLabel = "INSERT OR IGNORE"; break;
+ case OE_Rollback: zLabel = "INSERT OR ROLLBACK"; break;
+ case OE_Abort: zLabel = "INSERT OR ABORT"; break;
+ case OE_Fail: zLabel = "INSERT OR FAIL"; break;
+ }
+ sqlcipher_sqlite3TreeViewPush(&pView, 0);
+ sqlcipher_sqlite3TreeViewLine(pView, zLabel);
+ if( pWith ) n++;
+ if( pTabList ) n++;
+ if( pColumnList ) n++;
+ if( pSelect ) n++;
+ if( pExprList ) n++;
+ if( pUpsert ) n++;
+ if( pTrigger ) n++;
+ if( pWith ){
+ sqlcipher_sqlite3TreeViewPush(&pView, (--n)>0);
+ sqlcipher_sqlite3TreeViewWith(pView, pWith, 0);
+ sqlcipher_sqlite3TreeViewPop(&pView);
+ }
+ if( pTabList ){
+ sqlcipher_sqlite3TreeViewPush(&pView, (--n)>0);
+ sqlcipher_sqlite3TreeViewLine(pView, "INTO");
+ sqlcipher_sqlite3TreeViewSrcList(pView, pTabList);
+ sqlcipher_sqlite3TreeViewPop(&pView);
+ }
+ if( pColumnList ){
+ sqlcipher_sqlite3TreeViewIdList(pView, pColumnList, (--n)>0, "COLUMNS");
+ }
+ if( pSelect ){
+ sqlcipher_sqlite3TreeViewPush(&pView, (--n)>0);
+ sqlcipher_sqlite3TreeViewLine(pView, "DATA-SOURCE");
+ sqlcipher_sqlite3TreeViewSelect(pView, pSelect, 0);
+ sqlcipher_sqlite3TreeViewPop(&pView);
+ }
+ if( pExprList ){
+ sqlcipher_sqlite3TreeViewExprList(pView, pExprList, (--n)>0, "VALUES");
+ }
+ if( pUpsert ){
+ sqlcipher_sqlite3TreeViewPush(&pView, (--n)>0);
+ sqlcipher_sqlite3TreeViewLine(pView, "UPSERT");
+ sqlcipher_sqlite3TreeViewUpsert(pView, pUpsert, 0);
+ sqlcipher_sqlite3TreeViewPop(&pView);
+ }
+ if( pTrigger ){
+ sqlcipher_sqlite3TreeViewTrigger(pView, pTrigger, (--n)>0, 1);
+ }
+ sqlcipher_sqlite3TreeViewPop(&pView);
+}
+#endif /* TREETRACE_ENABLED */
+
+#if TREETRACE_ENABLED
+/*
+** Generate a human-readable diagram of the data structure that go
+** into generating an UPDATE statement.
+*/
+SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewUpdate(
+ const With *pWith,
+ const SrcList *pTabList,
+ const ExprList *pChanges,
+ const Expr *pWhere,
+ int onError,
+ const ExprList *pOrderBy,
+ const Expr *pLimit,
+ const Upsert *pUpsert,
+ const Trigger *pTrigger
+){
+ int n = 0;
+ TreeView *pView = 0;
+ const char *zLabel = "UPDATE";
+ switch( onError ){
+ case OE_Replace: zLabel = "UPDATE OR REPLACE"; break;
+ case OE_Ignore: zLabel = "UPDATE OR IGNORE"; break;
+ case OE_Rollback: zLabel = "UPDATE OR ROLLBACK"; break;
+ case OE_Abort: zLabel = "UPDATE OR ABORT"; break;
+ case OE_Fail: zLabel = "UPDATE OR FAIL"; break;
+ }
+ sqlcipher_sqlite3TreeViewPush(&pView, 0);
+ sqlcipher_sqlite3TreeViewLine(pView, zLabel);
+ if( pWith ) n++;
+ if( pTabList ) n++;
+ if( pChanges ) n++;
+ if( pWhere ) n++;
+ if( pOrderBy ) n++;
+ if( pLimit ) n++;
+ if( pUpsert ) n++;
+ if( pTrigger ) n++;
+ if( pWith ){
+ sqlcipher_sqlite3TreeViewPush(&pView, (--n)>0);
+ sqlcipher_sqlite3TreeViewWith(pView, pWith, 0);
+ sqlcipher_sqlite3TreeViewPop(&pView);
+ }
+ if( pTabList ){
+ sqlcipher_sqlite3TreeViewPush(&pView, (--n)>0);
+ sqlcipher_sqlite3TreeViewLine(pView, "FROM");
+ sqlcipher_sqlite3TreeViewSrcList(pView, pTabList);
+ sqlcipher_sqlite3TreeViewPop(&pView);
+ }
+ if( pChanges ){
+ sqlcipher_sqlite3TreeViewExprList(pView, pChanges, (--n)>0, "SET");
+ }
+ if( pWhere ){
+ sqlcipher_sqlite3TreeViewPush(&pView, (--n)>0);
+ sqlcipher_sqlite3TreeViewLine(pView, "WHERE");
+ sqlcipher_sqlite3TreeViewExpr(pView, pWhere, 0);
+ sqlcipher_sqlite3TreeViewPop(&pView);
+ }
+ if( pOrderBy ){
+ sqlcipher_sqlite3TreeViewExprList(pView, pOrderBy, (--n)>0, "ORDER-BY");
+ }
+ if( pLimit ){
+ sqlcipher_sqlite3TreeViewPush(&pView, (--n)>0);
+ sqlcipher_sqlite3TreeViewLine(pView, "LIMIT");
+ sqlcipher_sqlite3TreeViewExpr(pView, pLimit, 0);
+ sqlcipher_sqlite3TreeViewPop(&pView);
+ }
+ if( pUpsert ){
+ sqlcipher_sqlite3TreeViewPush(&pView, (--n)>0);
+ sqlcipher_sqlite3TreeViewLine(pView, "UPSERT");
+ sqlcipher_sqlite3TreeViewUpsert(pView, pUpsert, 0);
+ sqlcipher_sqlite3TreeViewPop(&pView);
+ }
+ if( pTrigger ){
+ sqlcipher_sqlite3TreeViewTrigger(pView, pTrigger, (--n)>0, 1);
+ }
+ sqlcipher_sqlite3TreeViewPop(&pView);
+}
+#endif /* TREETRACE_ENABLED */
+
+#ifndef SQLITE_OMIT_TRIGGER
+/*
+** Show a human-readable graph of a TriggerStep
+*/
+SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewTriggerStep(
+ TreeView *pView,
+ const TriggerStep *pStep,
+ u8 moreToFollow,
+ u8 showFullList
+){
+ int cnt = 0;
+ if( pStep==0 ) return;
+ sqlcipher_sqlite3TreeViewPush(&pView,
+ moreToFollow || (showFullList && pStep->pNext!=0));
+ do{
+ if( cnt++ && pStep->pNext==0 ){
+ sqlcipher_sqlite3TreeViewPop(&pView);
+ sqlcipher_sqlite3TreeViewPush(&pView, 0);
+ }
+ sqlcipher_sqlite3TreeViewLine(pView, "%s", pStep->zSpan ? pStep->zSpan : "RETURNING");
+ }while( showFullList && (pStep = pStep->pNext)!=0 );
+ sqlcipher_sqlite3TreeViewPop(&pView);
+}
+
+/*
+** Show a human-readable graph of a Trigger
+*/
+SQLITE_PRIVATE void sqlcipher_sqlite3TreeViewTrigger(
+ TreeView *pView,
+ const Trigger *pTrigger,
+ u8 moreToFollow,
+ u8 showFullList
+){
+ int cnt = 0;
+ if( pTrigger==0 ) return;
+ sqlcipher_sqlite3TreeViewPush(&pView,
+ moreToFollow || (showFullList && pTrigger->pNext!=0));
+ do{
+ if( cnt++ && pTrigger->pNext==0 ){
+ sqlcipher_sqlite3TreeViewPop(&pView);
+ sqlcipher_sqlite3TreeViewPush(&pView, 0);
+ }
+ sqlcipher_sqlite3TreeViewLine(pView, "TRIGGER %s", pTrigger->zName);
+ sqlcipher_sqlite3TreeViewPush(&pView, 0);
+ sqlcipher_sqlite3TreeViewTriggerStep(pView, pTrigger->step_list, 0, 1);
+ sqlcipher_sqlite3TreeViewPop(&pView);
+ }while( showFullList && (pTrigger = pTrigger->pNext)!=0 );
+ sqlcipher_sqlite3TreeViewPop(&pView);
+}
+#endif /* SQLITE_OMIT_TRIGGER */
+
+
+/*
+** These simplified versions of the tree-view routines omit unnecessary
+** parameters. These variants are intended to be used from a symbolic
+** debugger, such as "gdb", during interactive debugging sessions.
+**
+** This routines are given external linkage so that they will always be
+** accessible to the debugging, and to avoid warnings about unused
+** functions. But these routines only exist in debugging builds, so they
+** do not contaminate the interface.
+*/
+SQLITE_PRIVATE void sqlcipher_sqlite3ShowExpr(const Expr *p){ sqlcipher_sqlite3TreeViewExpr(0,p,0); }
+SQLITE_PRIVATE void sqlcipher_sqlite3ShowExprList(const ExprList *p){ sqlcipher_sqlite3TreeViewExprList(0,p,0,0);}
+SQLITE_PRIVATE void sqlcipher_sqlite3ShowIdList(const IdList *p){ sqlcipher_sqlite3TreeViewIdList(0,p,0,0); }
+SQLITE_PRIVATE void sqlcipher_sqlite3ShowSrcList(const SrcList *p){ sqlcipher_sqlite3TreeViewSrcList(0,p); }
+SQLITE_PRIVATE void sqlcipher_sqlite3ShowSelect(const Select *p){ sqlcipher_sqlite3TreeViewSelect(0,p,0); }
+SQLITE_PRIVATE void sqlcipher_sqlite3ShowWith(const With *p){ sqlcipher_sqlite3TreeViewWith(0,p,0); }
+SQLITE_PRIVATE void sqlcipher_sqlite3ShowUpsert(const Upsert *p){ sqlcipher_sqlite3TreeViewUpsert(0,p,0); }
+#ifndef SQLITE_OMIT_TRIGGER
+SQLITE_PRIVATE void sqlcipher_sqlite3ShowTriggerStep(const TriggerStep *p){
+ sqlcipher_sqlite3TreeViewTriggerStep(0,p,0,0);
+}
+SQLITE_PRIVATE void sqlcipher_sqlite3ShowTriggerStepList(const TriggerStep *p){
+ sqlcipher_sqlite3TreeViewTriggerStep(0,p,0,1);
}
+SQLITE_PRIVATE void sqlcipher_sqlite3ShowTrigger(const Trigger *p){ sqlcipher_sqlite3TreeViewTrigger(0,p,0,0); }
+SQLITE_PRIVATE void sqlcipher_sqlite3ShowTriggerList(const Trigger *p){ sqlcipher_sqlite3TreeViewTrigger(0,p,0,1);}
+#endif
+#ifndef SQLITE_OMIT_WINDOWFUNC
+SQLITE_PRIVATE void sqlcipher_sqlite3ShowWindow(const Window *p){ sqlcipher_sqlite3TreeViewWindow(0,p,0); }
+SQLITE_PRIVATE void sqlcipher_sqlite3ShowWinFunc(const Window *p){ sqlcipher_sqlite3TreeViewWinFunc(0,p,0); }
+#endif
#endif /* SQLITE_DEBUG */
@@ -35577,11 +32501,16 @@ SQLITE_API void sqlcipher_sqlite3_randomness(int N, void *pBuf){
** number generator) not as an encryption device.
*/
if( !wsdPrng.isInit ){
+ sqlcipher_sqlite3_vfs *pVfs = sqlcipher_sqlite3_vfs_find(0);
int i;
char k[256];
wsdPrng.j = 0;
wsdPrng.i = 0;
- sqlcipher_sqlite3OsRandomness(sqlcipher_sqlite3_vfs_find(0), 256, k);
+ if( NEVER(pVfs==0) ){
+ memset(k, 0, sizeof(k));
+ }else{
+ sqlcipher_sqlite3OsRandomness(pVfs, 256, k);
+ }
for(i=0; i<256; i++){
wsdPrng.s[i] = (u8)i;
}
@@ -36475,16 +33404,6 @@ SQLITE_PRIVATE void sqlcipher_sqlite3UtfSelfTest(void){
#endif
/*
-** Routine needed to support the testcase() macro.
-*/
-#ifdef SQLITE_COVERAGE_TEST
-SQLITE_PRIVATE void sqlcipher_sqlite3Coverage(int x){
- static unsigned dummy = 0;
- dummy += (unsigned)x;
-}
-#endif
-
-/*
** Calls to sqlcipher_sqlite3FaultSim() are used to simulate a failure during testing,
** or to bypass normal error detection during testing in order to let
** execute proceed futher downstream.
@@ -36513,11 +33432,21 @@ SQLITE_PRIVATE int sqlcipher_sqlite3FaultSim(int iTest){
#ifndef SQLITE_OMIT_FLOATING_POINT
/*
** Return true if the floating point value is Not a Number (NaN).
+**
+** Use the math library isnan() function if compiled with SQLITE_HAVE_ISNAN.
+** Otherwise, we have our own implementation that works on most systems.
*/
SQLITE_PRIVATE int sqlcipher_sqlite3IsNaN(double x){
+ int rc; /* The value return */
+#if !SQLITE_HAVE_ISNAN && !HAVE_ISNAN
u64 y;
memcpy(&y,&x,sizeof(y));
- return IsNaN(y);
+ rc = IsNaN(y);
+#else
+ rc = isnan(x);
+#endif /* HAVE_ISNAN */
+ testcase( rc );
+ return rc;
}
#endif /* SQLITE_OMIT_FLOATING_POINT */
@@ -36542,8 +33471,14 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Strlen30(const char *z){
** the column name if and only if the COLFLAG_HASTYPE flag is set.
*/
SQLITE_PRIVATE char *sqlcipher_sqlite3ColumnType(Column *pCol, char *zDflt){
- if( (pCol->colFlags & COLFLAG_HASTYPE)==0 ) return zDflt;
- return pCol->zName + strlen(pCol->zName) + 1;
+ if( pCol->colFlags & COLFLAG_HASTYPE ){
+ return pCol->zCnName + strlen(pCol->zCnName) + 1;
+ }else if( pCol->eCType ){
+ assert( pCol->eCType<=SQLITE_N_STDTYPE );
+ return (char*)sqlcipher_sqlite3StdType[pCol->eCType-1];
+ }else{
+ return zDflt;
+ }
}
/*
@@ -36564,7 +33499,22 @@ static SQLITE_NOINLINE void sqlcipher_sqlite3ErrorFinish(sqlcipher_sqlite3 *db,
SQLITE_PRIVATE void sqlcipher_sqlite3Error(sqlcipher_sqlite3 *db, int err_code){
assert( db!=0 );
db->errCode = err_code;
- if( err_code || db->pErr ) sqlcipher_sqlite3ErrorFinish(db, err_code);
+ if( err_code || db->pErr ){
+ sqlcipher_sqlite3ErrorFinish(db, err_code);
+ }else{
+ db->errByteOffset = -1;
+ }
+}
+
+/*
+** The equivalent of sqlcipher_sqlite3Error(db, SQLITE_OK). Clear the error state
+** and error message.
+*/
+SQLITE_PRIVATE void sqlcipher_sqlite3ErrorClear(sqlcipher_sqlite3 *db){
+ assert( db!=0 );
+ db->errCode = SQLITE_OK;
+ db->errByteOffset = -1;
+ if( db->pErr ) sqlcipher_sqlite3ValueSetNull(db->pErr);
}
/*
@@ -36584,17 +33534,8 @@ SQLITE_PRIVATE void sqlcipher_sqlite3SystemError(sqlcipher_sqlite3 *db, int rc){
** handle "db". The error code is set to "err_code".
**
** If it is not NULL, string zFormat specifies the format of the
-** error string in the style of the printf functions: The following
-** format characters are allowed:
-**
-** %s Insert a string
-** %z A string that should be freed after use
-** %d Insert an integer
-** %T Insert a token
-** %S Insert the first element of a SrcList
-**
-** zFormat and any string tokens that follow it are assumed to be
-** encoded in UTF-8.
+** error string. zFormat and any string tokens that follow it are
+** assumed to be encoded in UTF-8.
**
** To clear the most recent error for sqlite handle "db", sqlcipher_sqlite3Error
** should be called with err_code set to SQLITE_OK and zFormat set
@@ -36618,13 +33559,6 @@ SQLITE_PRIVATE void sqlcipher_sqlite3ErrorWithMsg(sqlcipher_sqlite3 *db, int err
/*
** Add an error message to pParse->zErrMsg and increment pParse->nErr.
-** The following formatting characters are allowed:
-**
-** %s Insert a string
-** %z A string that should be freed after use
-** %d Insert an integer
-** %T Insert a token
-** %S Insert the first element of a SrcList
**
** This function should be used to report any error that occurs while
** compiling an SQL statement (i.e. within sqlcipher_sqlite3_prepare()). The
@@ -36637,11 +33571,19 @@ SQLITE_PRIVATE void sqlcipher_sqlite3ErrorMsg(Parse *pParse, const char *zFormat
char *zMsg;
va_list ap;
sqlcipher_sqlite3 *db = pParse->db;
+ assert( db!=0 );
+ assert( db->pParse==pParse || db->pParse->pToplevel==pParse );
+ db->errByteOffset = -2;
va_start(ap, zFormat);
zMsg = sqlcipher_sqlite3VMPrintf(db, zFormat, ap);
va_end(ap);
+ if( db->errByteOffset<-1 ) db->errByteOffset = -1;
if( db->suppressErr ){
sqlcipher_sqlite3DbFree(db, zMsg);
+ if( db->mallocFailed ){
+ pParse->nErr++;
+ pParse->rc = SQLITE_NOMEM;
+ }
}else{
pParse->nErr++;
sqlcipher_sqlite3DbFree(db, pParse->zErrMsg);
@@ -36704,12 +33646,35 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Dequote(char *z){
z[j] = 0;
}
SQLITE_PRIVATE void sqlcipher_sqlite3DequoteExpr(Expr *p){
+ assert( !ExprHasProperty(p, EP_IntValue) );
assert( sqlcipher_sqlite3Isquote(p->u.zToken[0]) );
p->flags |= p->u.zToken[0]=='"' ? EP_Quoted|EP_DblQuoted : EP_Quoted;
sqlcipher_sqlite3Dequote(p->u.zToken);
}
/*
+** If the input token p is quoted, try to adjust the token to remove
+** the quotes. This is not always possible:
+**
+** "abc" -> abc
+** "ab""cd" -> (not possible because of the interior "")
+**
+** Remove the quotes if possible. This is a optimization. The overall
+** system should still return the correct answer even if this routine
+** is always a no-op.
+*/
+SQLITE_PRIVATE void sqlcipher_sqlite3DequoteToken(Token *p){
+ unsigned int i;
+ if( p->n<2 ) return;
+ if( !sqlcipher_sqlite3Isquote(p->z[0]) ) return;
+ for(i=1; i<p->n-1; i++){
+ if( sqlcipher_sqlite3Isquote(p->z[i]) ) return;
+ }
+ p->n -= 2;
+ p->z++;
+}
+
+/*
** Generate a Token object from a string
*/
SQLITE_PRIVATE void sqlcipher_sqlite3TokenInit(Token *p, char *z){
@@ -37816,13 +34781,13 @@ static void logBadConnection(const char *zType){
** used as an argument to sqlcipher_sqlite3_errmsg() or sqlcipher_sqlite3_close().
*/
SQLITE_PRIVATE int sqlcipher_sqlite3SafetyCheckOk(sqlcipher_sqlite3 *db){
- u32 magic;
+ u8 eOpenState;
if( db==0 ){
logBadConnection("NULL");
return 0;
}
- magic = db->magic;
- if( magic!=SQLITE_MAGIC_OPEN ){
+ eOpenState = db->eOpenState;
+ if( eOpenState!=SQLITE_STATE_OPEN ){
if( sqlcipher_sqlite3SafetyCheckSickOrOk(db) ){
testcase( sqlcipher_sqlite3GlobalConfig.xLog!=0 );
logBadConnection("unopened");
@@ -37833,11 +34798,11 @@ SQLITE_PRIVATE int sqlcipher_sqlite3SafetyCheckOk(sqlcipher_sqlite3 *db){
}
}
SQLITE_PRIVATE int sqlcipher_sqlite3SafetyCheckSickOrOk(sqlcipher_sqlite3 *db){
- u32 magic;
- magic = db->magic;
- if( magic!=SQLITE_MAGIC_SICK &&
- magic!=SQLITE_MAGIC_OPEN &&
- magic!=SQLITE_MAGIC_BUSY ){
+ u8 eOpenState;
+ eOpenState = db->eOpenState;
+ if( eOpenState!=SQLITE_STATE_SICK &&
+ eOpenState!=SQLITE_STATE_OPEN &&
+ eOpenState!=SQLITE_STATE_BUSY ){
testcase( sqlcipher_sqlite3GlobalConfig.xLog!=0 );
logBadConnection("invalid");
return 0;
@@ -38002,7 +34967,6 @@ SQLITE_PRIVATE LogEst sqlcipher_sqlite3LogEst(u64 x){
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).
@@ -38017,16 +34981,9 @@ SQLITE_PRIVATE LogEst sqlcipher_sqlite3LogEstFromDouble(double x){
e = (a>>52) - 1022;
return e*10;
}
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
-#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || \
- defined(SQLITE_ENABLE_STAT4) || \
- defined(SQLITE_EXPLAIN_ESTIMATED_ROWS)
/*
** Convert a LogEst into an integer.
-**
-** Note that this routine is only used when one or more of various
-** non-standard compile-time options is enabled.
*/
SQLITE_PRIVATE u64 sqlcipher_sqlite3LogEstToInt(LogEst x){
u64 n;
@@ -38034,17 +34991,9 @@ SQLITE_PRIVATE u64 sqlcipher_sqlite3LogEstToInt(LogEst x){
x /= 10;
if( n>=5 ) n -= 2;
else if( n>=1 ) n -= 1;
-#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || \
- defined(SQLITE_EXPLAIN_ESTIMATED_ROWS)
if( x>60 ) return (u64)LARGEST_INT64;
-#else
- /* If only SQLITE_ENABLE_STAT4 is on, then the largest input
- ** possible to this routine is 310, resulting in a maximum x of 31 */
- assert( x<=60 );
-#endif
return x>=3 ? (n+8)<<(x-3) : (n+8)>>(3-x);
}
-#endif /* defined SCANSTAT or STAT4 or ESTIMATED_ROWS */
/*
** Add a new name/number pair to a VList. This might require that the
@@ -38438,53 +35387,53 @@ SQLITE_PRIVATE const char *sqlcipher_sqlite3OpcodeName(int i){
/* 0 */ "Savepoint" OpHelp(""),
/* 1 */ "AutoCommit" OpHelp(""),
/* 2 */ "Transaction" OpHelp(""),
- /* 3 */ "SorterNext" OpHelp(""),
- /* 4 */ "Prev" OpHelp(""),
- /* 5 */ "Next" OpHelp(""),
- /* 6 */ "Checkpoint" OpHelp(""),
- /* 7 */ "JournalMode" OpHelp(""),
- /* 8 */ "Vacuum" OpHelp(""),
- /* 9 */ "VFilter" OpHelp("iplan=r[P3] zplan='P4'"),
- /* 10 */ "VUpdate" OpHelp("data=r[P3@P2]"),
- /* 11 */ "Goto" OpHelp(""),
- /* 12 */ "Gosub" OpHelp(""),
- /* 13 */ "InitCoroutine" OpHelp(""),
- /* 14 */ "Yield" OpHelp(""),
- /* 15 */ "MustBeInt" OpHelp(""),
- /* 16 */ "Jump" OpHelp(""),
- /* 17 */ "Once" OpHelp(""),
- /* 18 */ "If" OpHelp(""),
+ /* 3 */ "Checkpoint" OpHelp(""),
+ /* 4 */ "JournalMode" OpHelp(""),
+ /* 5 */ "Vacuum" OpHelp(""),
+ /* 6 */ "VFilter" OpHelp("iplan=r[P3] zplan='P4'"),
+ /* 7 */ "VUpdate" OpHelp("data=r[P3@P2]"),
+ /* 8 */ "Goto" OpHelp(""),
+ /* 9 */ "Gosub" OpHelp(""),
+ /* 10 */ "InitCoroutine" OpHelp(""),
+ /* 11 */ "Yield" OpHelp(""),
+ /* 12 */ "MustBeInt" OpHelp(""),
+ /* 13 */ "Jump" OpHelp(""),
+ /* 14 */ "Once" OpHelp(""),
+ /* 15 */ "If" OpHelp(""),
+ /* 16 */ "IfNot" OpHelp(""),
+ /* 17 */ "IsNullOrType" OpHelp("if typeof(r[P1]) IN (P3,5) goto P2"),
+ /* 18 */ "IfNullRow" OpHelp("if P1.nullRow then r[P3]=NULL, goto P2"),
/* 19 */ "Not" OpHelp("r[P2]= !r[P1]"),
- /* 20 */ "IfNot" OpHelp(""),
- /* 21 */ "IfNullRow" OpHelp("if P1.nullRow then r[P3]=NULL, goto P2"),
- /* 22 */ "SeekLT" OpHelp("key=r[P3@P4]"),
- /* 23 */ "SeekLE" OpHelp("key=r[P3@P4]"),
- /* 24 */ "SeekGE" OpHelp("key=r[P3@P4]"),
- /* 25 */ "SeekGT" OpHelp("key=r[P3@P4]"),
- /* 26 */ "IfNotOpen" OpHelp("if( !csr[P1] ) goto P2"),
- /* 27 */ "IfNoHope" OpHelp("key=r[P3@P4]"),
- /* 28 */ "NoConflict" OpHelp("key=r[P3@P4]"),
- /* 29 */ "NotFound" OpHelp("key=r[P3@P4]"),
- /* 30 */ "Found" OpHelp("key=r[P3@P4]"),
- /* 31 */ "SeekRowid" OpHelp("intkey=r[P3]"),
- /* 32 */ "NotExists" OpHelp("intkey=r[P3]"),
- /* 33 */ "Last" OpHelp(""),
- /* 34 */ "IfSmaller" OpHelp(""),
- /* 35 */ "SorterSort" OpHelp(""),
- /* 36 */ "Sort" OpHelp(""),
- /* 37 */ "Rewind" OpHelp(""),
- /* 38 */ "IdxLE" OpHelp("key=r[P3@P4]"),
- /* 39 */ "IdxGT" OpHelp("key=r[P3@P4]"),
- /* 40 */ "IdxLT" OpHelp("key=r[P3@P4]"),
- /* 41 */ "IdxGE" OpHelp("key=r[P3@P4]"),
- /* 42 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"),
+ /* 20 */ "SeekLT" OpHelp("key=r[P3@P4]"),
+ /* 21 */ "SeekLE" OpHelp("key=r[P3@P4]"),
+ /* 22 */ "SeekGE" OpHelp("key=r[P3@P4]"),
+ /* 23 */ "SeekGT" OpHelp("key=r[P3@P4]"),
+ /* 24 */ "IfNotOpen" OpHelp("if( !csr[P1] ) goto P2"),
+ /* 25 */ "IfNoHope" OpHelp("key=r[P3@P4]"),
+ /* 26 */ "NoConflict" OpHelp("key=r[P3@P4]"),
+ /* 27 */ "NotFound" OpHelp("key=r[P3@P4]"),
+ /* 28 */ "Found" OpHelp("key=r[P3@P4]"),
+ /* 29 */ "SeekRowid" OpHelp("intkey=r[P3]"),
+ /* 30 */ "NotExists" OpHelp("intkey=r[P3]"),
+ /* 31 */ "Last" OpHelp(""),
+ /* 32 */ "IfSmaller" OpHelp(""),
+ /* 33 */ "SorterSort" OpHelp(""),
+ /* 34 */ "Sort" OpHelp(""),
+ /* 35 */ "Rewind" OpHelp(""),
+ /* 36 */ "SorterNext" OpHelp(""),
+ /* 37 */ "Prev" OpHelp(""),
+ /* 38 */ "Next" OpHelp(""),
+ /* 39 */ "IdxLE" OpHelp("key=r[P3@P4]"),
+ /* 40 */ "IdxGT" OpHelp("key=r[P3@P4]"),
+ /* 41 */ "IdxLT" OpHelp("key=r[P3@P4]"),
+ /* 42 */ "IdxGE" OpHelp("key=r[P3@P4]"),
/* 43 */ "Or" OpHelp("r[P3]=(r[P1] || r[P2])"),
/* 44 */ "And" OpHelp("r[P3]=(r[P1] && r[P2])"),
- /* 45 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"),
- /* 46 */ "Program" OpHelp(""),
- /* 47 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"),
- /* 48 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"),
- /* 49 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"),
+ /* 45 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"),
+ /* 46 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"),
+ /* 47 */ "Program" OpHelp(""),
+ /* 48 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"),
+ /* 49 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"),
/* 50 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"),
/* 51 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"),
/* 52 */ "Ne" OpHelp("IF r[P3]!=r[P1]"),
@@ -38493,125 +35442,135 @@ SQLITE_PRIVATE const char *sqlcipher_sqlite3OpcodeName(int i){
/* 55 */ "Le" OpHelp("IF r[P3]<=r[P1]"),
/* 56 */ "Lt" OpHelp("IF r[P3]<r[P1]"),
/* 57 */ "Ge" OpHelp("IF r[P3]>=r[P1]"),
- /* 58 */ "ElseNotEq" OpHelp(""),
- /* 59 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"),
- /* 60 */ "IncrVacuum" OpHelp(""),
- /* 61 */ "VNext" OpHelp(""),
- /* 62 */ "Init" OpHelp("Start at P2"),
- /* 63 */ "PureFunc" OpHelp("r[P3]=func(r[P2@NP])"),
- /* 64 */ "Function" OpHelp("r[P3]=func(r[P2@NP])"),
- /* 65 */ "Return" OpHelp(""),
- /* 66 */ "EndCoroutine" OpHelp(""),
- /* 67 */ "HaltIfNull" OpHelp("if r[P3]=null halt"),
- /* 68 */ "Halt" OpHelp(""),
- /* 69 */ "Integer" OpHelp("r[P2]=P1"),
- /* 70 */ "Int64" OpHelp("r[P2]=P4"),
- /* 71 */ "String" OpHelp("r[P2]='P4' (len=P1)"),
- /* 72 */ "Null" OpHelp("r[P2..P3]=NULL"),
- /* 73 */ "SoftNull" OpHelp("r[P1]=NULL"),
- /* 74 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"),
- /* 75 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"),
- /* 76 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"),
- /* 77 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"),
- /* 78 */ "SCopy" OpHelp("r[P2]=r[P1]"),
- /* 79 */ "IntCopy" OpHelp("r[P2]=r[P1]"),
- /* 80 */ "ResultRow" OpHelp("output=r[P1@P2]"),
- /* 81 */ "CollSeq" OpHelp(""),
- /* 82 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"),
- /* 83 */ "RealAffinity" OpHelp(""),
- /* 84 */ "Cast" OpHelp("affinity(r[P1])"),
- /* 85 */ "Permutation" OpHelp(""),
- /* 86 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"),
- /* 87 */ "IsTrue" OpHelp("r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4"),
- /* 88 */ "Offset" OpHelp("r[P3] = sqlite_offset(P1)"),
- /* 89 */ "Column" OpHelp("r[P3]=PX"),
- /* 90 */ "Affinity" OpHelp("affinity(r[P1@P2])"),
- /* 91 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"),
- /* 92 */ "Count" OpHelp("r[P2]=count()"),
- /* 93 */ "ReadCookie" OpHelp(""),
- /* 94 */ "SetCookie" OpHelp(""),
- /* 95 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"),
- /* 96 */ "OpenRead" OpHelp("root=P2 iDb=P3"),
- /* 97 */ "OpenWrite" OpHelp("root=P2 iDb=P3"),
- /* 98 */ "OpenDup" OpHelp(""),
- /* 99 */ "OpenAutoindex" OpHelp("nColumn=P2"),
- /* 100 */ "OpenEphemeral" OpHelp("nColumn=P2"),
- /* 101 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"),
- /* 102 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"),
- /* 103 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<<r[P1]"),
- /* 104 */ "ShiftRight" OpHelp("r[P3]=r[P2]>>r[P1]"),
- /* 105 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"),
- /* 106 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"),
- /* 107 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"),
- /* 108 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"),
- /* 109 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"),
- /* 110 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"),
- /* 111 */ "SorterOpen" OpHelp(""),
- /* 112 */ "BitNot" OpHelp("r[P2]= ~r[P1]"),
- /* 113 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"),
- /* 114 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"),
- /* 115 */ "String8" OpHelp("r[P2]='P4'"),
- /* 116 */ "Close" OpHelp(""),
- /* 117 */ "ColumnsUsed" OpHelp(""),
- /* 118 */ "SeekScan" OpHelp("Scan-ahead up to P1 rows"),
- /* 119 */ "SeekHit" OpHelp("set P2<=seekHit<=P3"),
- /* 120 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"),
- /* 121 */ "NewRowid" OpHelp("r[P2]=rowid"),
- /* 122 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"),
- /* 123 */ "Delete" OpHelp(""),
- /* 124 */ "ResetCount" OpHelp(""),
- /* 125 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),
- /* 126 */ "SorterData" OpHelp("r[P2]=data"),
- /* 127 */ "RowData" OpHelp("r[P2]=data"),
- /* 128 */ "Rowid" OpHelp("r[P2]=rowid"),
- /* 129 */ "NullRow" OpHelp(""),
- /* 130 */ "SeekEnd" OpHelp(""),
- /* 131 */ "IdxInsert" OpHelp("key=r[P2]"),
- /* 132 */ "SorterInsert" OpHelp("key=r[P2]"),
- /* 133 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
- /* 134 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"),
- /* 135 */ "IdxRowid" OpHelp("r[P2]=rowid"),
- /* 136 */ "FinishSeek" OpHelp(""),
- /* 137 */ "Destroy" OpHelp(""),
- /* 138 */ "Clear" OpHelp(""),
- /* 139 */ "ResetSorter" OpHelp(""),
- /* 140 */ "CreateBtree" OpHelp("r[P2]=root iDb=P1 flags=P3"),
- /* 141 */ "SqlExec" OpHelp(""),
- /* 142 */ "ParseSchema" OpHelp(""),
- /* 143 */ "LoadAnalysis" OpHelp(""),
- /* 144 */ "DropTable" OpHelp(""),
- /* 145 */ "DropIndex" OpHelp(""),
- /* 146 */ "DropTrigger" OpHelp(""),
- /* 147 */ "IntegrityCk" OpHelp(""),
- /* 148 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"),
- /* 149 */ "Param" OpHelp(""),
- /* 150 */ "Real" OpHelp("r[P2]=P4"),
- /* 151 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
- /* 152 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"),
- /* 153 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"),
- /* 154 */ "AggInverse" OpHelp("accum=r[P3] inverse(r[P2@P5])"),
- /* 155 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"),
- /* 156 */ "AggStep1" OpHelp("accum=r[P3] step(r[P2@P5])"),
- /* 157 */ "AggValue" OpHelp("r[P3]=value N=P2"),
- /* 158 */ "AggFinal" OpHelp("accum=r[P1] N=P2"),
- /* 159 */ "Expire" OpHelp(""),
- /* 160 */ "CursorLock" OpHelp(""),
- /* 161 */ "CursorUnlock" OpHelp(""),
- /* 162 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
- /* 163 */ "VBegin" OpHelp(""),
- /* 164 */ "VCreate" OpHelp(""),
- /* 165 */ "VDestroy" OpHelp(""),
- /* 166 */ "VOpen" OpHelp(""),
- /* 167 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
- /* 168 */ "VRename" OpHelp(""),
- /* 169 */ "Pagecount" OpHelp(""),
- /* 170 */ "MaxPgcnt" OpHelp(""),
- /* 171 */ "Trace" OpHelp(""),
- /* 172 */ "CursorHint" OpHelp(""),
- /* 173 */ "ReleaseReg" OpHelp("release r[P1@P2] mask P3"),
- /* 174 */ "Noop" OpHelp(""),
- /* 175 */ "Explain" OpHelp(""),
- /* 176 */ "Abortable" OpHelp(""),
+ /* 58 */ "ElseEq" OpHelp(""),
+ /* 59 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"),
+ /* 60 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"),
+ /* 61 */ "IncrVacuum" OpHelp(""),
+ /* 62 */ "VNext" OpHelp(""),
+ /* 63 */ "Filter" OpHelp("if key(P3@P4) not in filter(P1) goto P2"),
+ /* 64 */ "Init" OpHelp("Start at P2"),
+ /* 65 */ "PureFunc" OpHelp("r[P3]=func(r[P2@NP])"),
+ /* 66 */ "Function" OpHelp("r[P3]=func(r[P2@NP])"),
+ /* 67 */ "Return" OpHelp(""),
+ /* 68 */ "EndCoroutine" OpHelp(""),
+ /* 69 */ "HaltIfNull" OpHelp("if r[P3]=null halt"),
+ /* 70 */ "Halt" OpHelp(""),
+ /* 71 */ "Integer" OpHelp("r[P2]=P1"),
+ /* 72 */ "Int64" OpHelp("r[P2]=P4"),
+ /* 73 */ "String" OpHelp("r[P2]='P4' (len=P1)"),
+ /* 74 */ "BeginSubrtn" OpHelp("r[P2]=NULL"),
+ /* 75 */ "Null" OpHelp("r[P2..P3]=NULL"),
+ /* 76 */ "SoftNull" OpHelp("r[P1]=NULL"),
+ /* 77 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"),
+ /* 78 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"),
+ /* 79 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"),
+ /* 80 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"),
+ /* 81 */ "SCopy" OpHelp("r[P2]=r[P1]"),
+ /* 82 */ "IntCopy" OpHelp("r[P2]=r[P1]"),
+ /* 83 */ "FkCheck" OpHelp(""),
+ /* 84 */ "ResultRow" OpHelp("output=r[P1@P2]"),
+ /* 85 */ "CollSeq" OpHelp(""),
+ /* 86 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"),
+ /* 87 */ "RealAffinity" OpHelp(""),
+ /* 88 */ "Cast" OpHelp("affinity(r[P1])"),
+ /* 89 */ "Permutation" OpHelp(""),
+ /* 90 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"),
+ /* 91 */ "IsTrue" OpHelp("r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4"),
+ /* 92 */ "ZeroOrNull" OpHelp("r[P2] = 0 OR NULL"),
+ /* 93 */ "Offset" OpHelp("r[P3] = sqlite_offset(P1)"),
+ /* 94 */ "Column" OpHelp("r[P3]=PX cursor P1 column P2"),
+ /* 95 */ "TypeCheck" OpHelp("typecheck(r[P1@P2])"),
+ /* 96 */ "Affinity" OpHelp("affinity(r[P1@P2])"),
+ /* 97 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"),
+ /* 98 */ "Count" OpHelp("r[P2]=count()"),
+ /* 99 */ "ReadCookie" OpHelp(""),
+ /* 100 */ "SetCookie" OpHelp(""),
+ /* 101 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"),
+ /* 102 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"),
+ /* 103 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"),
+ /* 104 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<<r[P1]"),
+ /* 105 */ "ShiftRight" OpHelp("r[P3]=r[P2]>>r[P1]"),
+ /* 106 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"),
+ /* 107 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"),
+ /* 108 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"),
+ /* 109 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"),
+ /* 110 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"),
+ /* 111 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"),
+ /* 112 */ "OpenRead" OpHelp("root=P2 iDb=P3"),
+ /* 113 */ "OpenWrite" OpHelp("root=P2 iDb=P3"),
+ /* 114 */ "BitNot" OpHelp("r[P2]= ~r[P1]"),
+ /* 115 */ "OpenDup" OpHelp(""),
+ /* 116 */ "OpenAutoindex" OpHelp("nColumn=P2"),
+ /* 117 */ "String8" OpHelp("r[P2]='P4'"),
+ /* 118 */ "OpenEphemeral" OpHelp("nColumn=P2"),
+ /* 119 */ "SorterOpen" OpHelp(""),
+ /* 120 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"),
+ /* 121 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"),
+ /* 122 */ "Close" OpHelp(""),
+ /* 123 */ "ColumnsUsed" OpHelp(""),
+ /* 124 */ "SeekScan" OpHelp("Scan-ahead up to P1 rows"),
+ /* 125 */ "SeekHit" OpHelp("set P2<=seekHit<=P3"),
+ /* 126 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"),
+ /* 127 */ "NewRowid" OpHelp("r[P2]=rowid"),
+ /* 128 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"),
+ /* 129 */ "RowCell" OpHelp(""),
+ /* 130 */ "Delete" OpHelp(""),
+ /* 131 */ "ResetCount" OpHelp(""),
+ /* 132 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),
+ /* 133 */ "SorterData" OpHelp("r[P2]=data"),
+ /* 134 */ "RowData" OpHelp("r[P2]=data"),
+ /* 135 */ "Rowid" OpHelp("r[P2]=PX rowid of P1"),
+ /* 136 */ "NullRow" OpHelp(""),
+ /* 137 */ "SeekEnd" OpHelp(""),
+ /* 138 */ "IdxInsert" OpHelp("key=r[P2]"),
+ /* 139 */ "SorterInsert" OpHelp("key=r[P2]"),
+ /* 140 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
+ /* 141 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"),
+ /* 142 */ "IdxRowid" OpHelp("r[P2]=rowid"),
+ /* 143 */ "FinishSeek" OpHelp(""),
+ /* 144 */ "Destroy" OpHelp(""),
+ /* 145 */ "Clear" OpHelp(""),
+ /* 146 */ "ResetSorter" OpHelp(""),
+ /* 147 */ "CreateBtree" OpHelp("r[P2]=root iDb=P1 flags=P3"),
+ /* 148 */ "SqlExec" OpHelp(""),
+ /* 149 */ "ParseSchema" OpHelp(""),
+ /* 150 */ "LoadAnalysis" OpHelp(""),
+ /* 151 */ "DropTable" OpHelp(""),
+ /* 152 */ "DropIndex" OpHelp(""),
+ /* 153 */ "Real" OpHelp("r[P2]=P4"),
+ /* 154 */ "DropTrigger" OpHelp(""),
+ /* 155 */ "IntegrityCk" OpHelp(""),
+ /* 156 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"),
+ /* 157 */ "Param" OpHelp(""),
+ /* 158 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
+ /* 159 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"),
+ /* 160 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"),
+ /* 161 */ "AggInverse" OpHelp("accum=r[P3] inverse(r[P2@P5])"),
+ /* 162 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"),
+ /* 163 */ "AggStep1" OpHelp("accum=r[P3] step(r[P2@P5])"),
+ /* 164 */ "AggValue" OpHelp("r[P3]=value N=P2"),
+ /* 165 */ "AggFinal" OpHelp("accum=r[P1] N=P2"),
+ /* 166 */ "Expire" OpHelp(""),
+ /* 167 */ "CursorLock" OpHelp(""),
+ /* 168 */ "CursorUnlock" OpHelp(""),
+ /* 169 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
+ /* 170 */ "VBegin" OpHelp(""),
+ /* 171 */ "VCreate" OpHelp(""),
+ /* 172 */ "VDestroy" OpHelp(""),
+ /* 173 */ "VOpen" OpHelp(""),
+ /* 174 */ "VInitIn" OpHelp("r[P2]=ValueList(P1,P3)"),
+ /* 175 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
+ /* 176 */ "VRename" OpHelp(""),
+ /* 177 */ "Pagecount" OpHelp(""),
+ /* 178 */ "MaxPgcnt" OpHelp(""),
+ /* 179 */ "ClrSubtype" OpHelp("r[P1].subtype = 0"),
+ /* 180 */ "FilterAdd" OpHelp("filter(P1) += key(P3@P4)"),
+ /* 181 */ "Trace" OpHelp(""),
+ /* 182 */ "CursorHint" OpHelp(""),
+ /* 183 */ "ReleaseReg" OpHelp("release r[P1@P2] mask P3"),
+ /* 184 */ "Noop" OpHelp(""),
+ /* 185 */ "Explain" OpHelp(""),
+ /* 186 */ "Abortable" OpHelp(""),
};
return azName[i];
}
@@ -38712,12 +35671,12 @@ SQLITE_PRIVATE const char *sqlcipher_sqlite3OpcodeName(int i){
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
-/* #include <unistd.h> */
+#include <unistd.h>
/* #include <time.h> */
#include <sys/time.h>
-/* #include <errno.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
@@ -38918,205 +35877,7 @@ static pid_t randomnessPid = 0;
/*
** Include code that is common to all os_*.c files
*/
-/************** Include os_common.h in the middle of os_unix.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
-
-/*
-** 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 and x86_64 class CPUs.
-*/
-#ifndef SQLITE_HWTIME_H
-#define SQLITE_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(__STRICT_ANSI__) && \
- (defined(__GNUC__) || defined(_MSC_VER)) && \
- (defined(i386) || defined(__i386__) || defined(_M_IX86))
-
- #if defined(__GNUC__)
-
- __inline__ sqlite_uint64 sqlcipher_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 sqlcipher_sqlite3Hwtime(void){
- __asm {
- rdtsc
- ret ; return value at EDX:EAX
- }
- }
-
- #endif
-
-#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__))
-
- __inline__ sqlite_uint64 sqlcipher_sqlite3Hwtime(void){
- unsigned long val;
- __asm__ __volatile__ ("rdtsc" : "=A" (val));
- return val;
- }
-
-#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__))
-
- __inline__ sqlite_uint64 sqlcipher_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
-
- /*
- ** asm() is needed for hardware timing support. Without asm(),
- ** disable the sqlcipher_sqlite3Hwtime() routine.
- **
- ** sqlcipher_sqlite3Hwtime() is only used for some obscure debugging
- ** and analysis configurations, not in any deliverable, so this
- ** should not be a great loss.
- */
-SQLITE_PRIVATE sqlite_uint64 sqlcipher_sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
-
-#endif
-
-#endif /* !defined(SQLITE_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=sqlcipher_sqlite3Hwtime()
-#define TIMER_END g_elapsed=sqlcipher_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.
-*/
-#if defined(SQLITE_TEST)
-SQLITE_API extern int sqlcipher_sqlite3_io_error_hit;
-SQLITE_API extern int sqlcipher_sqlite3_io_error_hardhit;
-SQLITE_API extern int sqlcipher_sqlite3_io_error_pending;
-SQLITE_API extern int sqlcipher_sqlite3_io_error_persist;
-SQLITE_API extern int sqlcipher_sqlite3_io_error_benign;
-SQLITE_API extern int sqlcipher_sqlite3_diskfull_pending;
-SQLITE_API extern int sqlcipher_sqlite3_diskfull;
-#define SimulateIOErrorBenign(X) sqlcipher_sqlite3_io_error_benign=(X)
-#define SimulateIOError(CODE) \
- if( (sqlcipher_sqlite3_io_error_persist && sqlcipher_sqlite3_io_error_hit) \
- || sqlcipher_sqlite3_io_error_pending-- == 1 ) \
- { local_ioerr(); CODE; }
-static void local_ioerr(){
- IOTRACE(("IOERR\n"));
- sqlcipher_sqlite3_io_error_hit++;
- if( !sqlcipher_sqlite3_io_error_benign ) sqlcipher_sqlite3_io_error_hardhit++;
-}
-#define SimulateDiskfullError(CODE) \
- if( sqlcipher_sqlite3_diskfull_pending ){ \
- if( sqlcipher_sqlite3_diskfull_pending == 1 ){ \
- local_ioerr(); \
- sqlcipher_sqlite3_diskfull = 1; \
- sqlcipher_sqlite3_io_error_hit = 1; \
- CODE; \
- }else{ \
- sqlcipher_sqlite3_diskfull_pending--; \
- } \
- }
-#else
-#define SimulateIOErrorBenign(X)
-#define SimulateIOError(A)
-#define SimulateDiskfullError(A)
-#endif /* defined(SQLITE_TEST) */
-
-/*
-** When testing, keep a count of the number of open files.
-*/
-#if defined(SQLITE_TEST)
-SQLITE_API extern int sqlcipher_sqlite3_open_file_count;
-#define OpenCounter(X) sqlcipher_sqlite3_open_file_count+=(X)
-#else
-#define OpenCounter(X)
-#endif /* defined(SQLITE_TEST) */
-
-#endif /* !defined(_OS_COMMON_H_) */
-
-/************** End of os_common.h *******************************************/
-/************** Continuing where we left off in os_unix.c ********************/
+/* #include "os_common.h" */
/*
** Define various macros that are missing from some systems.
@@ -42770,6 +39531,9 @@ static void unixModeBit(unixFile *pFile, unsigned char mask, int *pArg){
/* Forward declaration */
static int unixGetTempname(int nBuf, char *zBuf);
+#ifndef SQLITE_OMIT_WAL
+ static int unixFcntlExternalReader(unixFile*, int*);
+#endif
/*
** Information and control of an open file handle.
@@ -42886,6 +39650,15 @@ static int unixFileControl(sqlcipher_sqlite3_file *id, int op, void *pArg){
return proxyFileControl(id,op,pArg);
}
#endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */
+
+ case SQLITE_FCNTL_EXTERNAL_READER: {
+#ifndef SQLITE_OMIT_WAL
+ return unixFcntlExternalReader((unixFile*)id, (int*)pArg);
+#else
+ *(int*)pArg = 0;
+ return SQLITE_OK;
+#endif
+ }
}
return SQLITE_NOTFOUND;
}
@@ -43132,6 +39905,40 @@ struct unixShm {
#define UNIX_SHM_DMS (UNIX_SHM_BASE+SQLITE_SHM_NLOCK) /* deadman switch */
/*
+** Use F_GETLK to check whether or not there are any readers with open
+** wal-mode transactions in other processes on database file pFile. If
+** no error occurs, return SQLITE_OK and set (*piOut) to 1 if there are
+** such transactions, or 0 otherwise. If an error occurs, return an
+** SQLite error code. The final value of *piOut is undefined in this
+** case.
+*/
+static int unixFcntlExternalReader(unixFile *pFile, int *piOut){
+ int rc = SQLITE_OK;
+ *piOut = 0;
+ if( pFile->pShm){
+ unixShmNode *pShmNode = pFile->pShm->pShmNode;
+ struct flock f;
+
+ memset(&f, 0, sizeof(f));
+ f.l_type = F_WRLCK;
+ f.l_whence = SEEK_SET;
+ f.l_start = UNIX_SHM_BASE + 3;
+ f.l_len = SQLITE_SHM_NLOCK - 3;
+
+ sqlcipher_sqlite3_mutex_enter(pShmNode->pShmMutex);
+ if( osFcntl(pShmNode->hShm, F_GETLK, &f)<0 ){
+ rc = SQLITE_IOERR_LOCK;
+ }else{
+ *piOut = (f.l_type!=F_UNLCK);
+ }
+ sqlcipher_sqlite3_mutex_leave(pShmNode->pShmMutex);
+ }
+
+ return rc;
+}
+
+
+/*
** Apply posix advisory locks for all bytes from ofst through ofst+n-1.
**
** Locks block if the mask is exactly UNIX_SHM_C and are non-blocking
@@ -43683,11 +40490,17 @@ static int unixShmLock(
int flags /* What to do with the lock */
){
unixFile *pDbFd = (unixFile*)fd; /* Connection holding shared memory */
- unixShm *p = pDbFd->pShm; /* The shared memory being locked */
- unixShmNode *pShmNode = p->pShmNode; /* The underlying file iNode */
+ unixShm *p; /* The shared memory being locked */
+ unixShmNode *pShmNode; /* The underlying file iNode */
int rc = SQLITE_OK; /* Result code */
u16 mask; /* Mask of locks to take or release */
- int *aLock = pShmNode->aLock;
+ int *aLock;
+
+ p = pDbFd->pShm;
+ if( p==0 ) return SQLITE_IOERR_SHMLOCK;
+ pShmNode = p->pShmNode;
+ if( NEVER(pShmNode==0) ) return SQLITE_IOERR_SHMLOCK;
+ aLock = pShmNode->aLock;
assert( pShmNode==pDbFd->pInode->pShmNode );
assert( pShmNode->pInode==pDbFd->pInode );
@@ -44572,24 +41385,34 @@ static int fillInUnixFile(
}
/*
+** Directories to consider for temp files.
+*/
+static const char *azTempDirs[] = {
+ 0,
+ 0,
+ "/var/tmp",
+ "/usr/tmp",
+ "/tmp",
+ "."
+};
+
+/*
+** Initialize first two members of azTempDirs[] array.
+*/
+static void unixTempFileInit(void){
+ azTempDirs[0] = getenv("SQLITE_TMPDIR");
+ azTempDirs[1] = getenv("TMPDIR");
+}
+
+/*
** Return the name of a directory in which to put temporary files.
** If no suitable temporary file directory can be found, return NULL.
*/
static const char *unixTempFileDir(void){
- static const char *azDirs[] = {
- 0,
- 0,
- "/var/tmp",
- "/usr/tmp",
- "/tmp",
- "."
- };
unsigned int i = 0;
struct stat buf;
const char *zDir = sqlcipher_sqlite3_temp_directory;
- if( !azDirs[0] ) azDirs[0] = getenv("SQLITE_TMPDIR");
- if( !azDirs[1] ) azDirs[1] = getenv("TMPDIR");
while(1){
if( zDir!=0
&& osStat(zDir, &buf)==0
@@ -44598,8 +41421,8 @@ static const char *unixTempFileDir(void){
){
return zDir;
}
- if( i>=sizeof(azDirs)/sizeof(azDirs[0]) ) break;
- zDir = azDirs[i++];
+ if( i>=sizeof(azTempDirs)/sizeof(azTempDirs[0]) ) break;
+ zDir = azTempDirs[i++];
}
return 0;
}
@@ -44612,6 +41435,7 @@ static const char *unixTempFileDir(void){
static int unixGetTempname(int nBuf, char *zBuf){
const char *zDir;
int iLimit = 0;
+ int rc = SQLITE_OK;
/* 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
@@ -44620,18 +41444,26 @@ static int unixGetTempname(int nBuf, char *zBuf){
zBuf[0] = 0;
SimulateIOError( return SQLITE_IOERR );
+ sqlcipher_sqlite3_mutex_enter(sqlcipher_sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
zDir = unixTempFileDir();
- if( zDir==0 ) return SQLITE_IOERR_GETTEMPPATH;
- do{
- u64 r;
- sqlcipher_sqlite3_randomness(sizeof(r), &r);
- assert( nBuf>2 );
- zBuf[nBuf-2] = 0;
- sqlcipher_sqlite3_snprintf(nBuf, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX"%llx%c",
- zDir, r, 0);
- if( zBuf[nBuf-2]!=0 || (iLimit++)>10 ) return SQLITE_ERROR;
- }while( osAccess(zBuf,0)==0 );
- return SQLITE_OK;
+ if( zDir==0 ){
+ rc = SQLITE_IOERR_GETTEMPPATH;
+ }else{
+ do{
+ u64 r;
+ sqlcipher_sqlite3_randomness(sizeof(r), &r);
+ assert( nBuf>2 );
+ zBuf[nBuf-2] = 0;
+ sqlcipher_sqlite3_snprintf(nBuf, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX"%llx%c",
+ zDir, r, 0);
+ if( zBuf[nBuf-2]!=0 || (iLimit++)>10 ){
+ rc = SQLITE_ERROR;
+ break;
+ }
+ }while( osAccess(zBuf,0)==0 );
+ }
+ sqlcipher_sqlite3_mutex_leave(sqlcipher_sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
+ return rc;
}
#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
@@ -44774,20 +41606,23 @@ static int findCreateFileMode(
**
** where NN is a decimal number. The NN naming schemes are
** used by the test_multiplex.c module.
+ **
+ ** In normal operation, the journal file name will always contain
+ ** a '-' character. However in 8+3 filename mode, or if a corrupt
+ ** rollback journal specifies a super-journal with a goofy name, then
+ ** the '-' might be missing or the '-' might be the first character in
+ ** the filename. In that case, just return SQLITE_OK with *pMode==0.
*/
nDb = sqlcipher_sqlite3Strlen30(zPath) - 1;
- while( zPath[nDb]!='-' ){
- /* In normal operation, the journal file name will always contain
- ** a '-' character. However in 8+3 filename mode, or if a corrupt
- ** rollback journal specifies a super-journal with a goofy name, then
- ** the '-' might be missing. */
- if( nDb==0 || zPath[nDb]=='.' ) return SQLITE_OK;
+ while( nDb>0 && zPath[nDb]!='.' ){
+ if( zPath[nDb]=='-' ){
+ memcpy(zDb, zPath, nDb);
+ zDb[nDb] = '\0';
+ rc = getFileMode(zDb, pMode, pUid, pGid);
+ break;
+ }
nDb--;
}
- memcpy(zDb, zPath, nDb);
- zDb[nDb] = '\0';
-
- rc = getFileMode(zDb, pMode, pUid, pGid);
}else if( flags & SQLITE_OPEN_DELETEONCLOSE ){
*pMode = 0600;
}else if( flags & SQLITE_OPEN_URI ){
@@ -44905,6 +41740,11 @@ static int unixOpen(
}
memset(p, 0, sizeof(unixFile));
+#ifdef SQLITE_ASSERT_NO_FILES
+ /* Applications that never read or write a persistent disk files */
+ assert( zName==0 );
+#endif
+
if( eType==SQLITE_OPEN_MAIN_DB ){
UnixUnusedFd *pUnused;
pUnused = findReusableFd(zName, flags);
@@ -45172,85 +42012,99 @@ static int unixAccess(
}
/*
-** If the last component of the pathname in z[0]..z[j-1] is something
-** other than ".." then back it out and return true. If the last
-** component is empty or if it is ".." then return false.
+** A pathname under construction
*/
-static int unixBackupDir(const char *z, int *pJ){
- int j = *pJ;
- int i;
- if( j<=0 ) return 0;
- for(i=j-1; ALWAYS(i>0) && z[i-1]!='/'; i--){}
- if( z[i]=='.' && i==j-2 && z[i+1]=='.' ) return 0;
- *pJ = i-1;
- return 1;
-}
+typedef struct DbPath DbPath;
+struct DbPath {
+ int rc; /* Non-zero following any error */
+ int nSymlink; /* Number of symlinks resolved */
+ char *zOut; /* Write the pathname here */
+ int nOut; /* Bytes of space available to zOut[] */
+ int nUsed; /* Bytes of zOut[] currently being used */
+};
+
+/* Forward reference */
+static void appendAllPathElements(DbPath*,const char*);
/*
-** Convert a relative pathname into a full pathname. Also
-** simplify the pathname as follows:
-**
-** Remove all instances of /./
-** Remove all isntances of /X/../ for any X
+** Append a single path element to the DbPath under construction
*/
-static int mkFullPathname(
- const char *zPath, /* Input path */
- char *zOut, /* Output buffer */
- int nOut /* Allocated size of buffer zOut */
+static void appendOnePathElement(
+ DbPath *pPath, /* Path under construction, to which to append zName */
+ const char *zName, /* Name to append to pPath. Not zero-terminated */
+ int nName /* Number of significant bytes in zName */
){
- int nPath = sqlcipher_sqlite3Strlen30(zPath);
- int iOff = 0;
- int i, j;
- if( zPath[0]!='/' ){
- if( osGetcwd(zOut, nOut-2)==0 ){
- return unixLogError(SQLITE_CANTOPEN_BKPT, "getcwd", zPath);
+ assert( nName>0 );
+ assert( zName!=0 );
+ if( zName[0]=='.' ){
+ if( nName==1 ) return;
+ if( zName[1]=='.' && nName==2 ){
+ if( pPath->nUsed<=1 ){
+ pPath->rc = SQLITE_ERROR;
+ return;
+ }
+ assert( pPath->zOut[0]=='/' );
+ while( pPath->zOut[--pPath->nUsed]!='/' ){}
+ return;
}
- iOff = sqlcipher_sqlite3Strlen30(zOut);
- zOut[iOff++] = '/';
- }
- if( (iOff+nPath+1)>nOut ){
- /* SQLite assumes that xFullPathname() nul-terminates the output buffer
- ** even if it returns an error. */
- zOut[iOff] = '\0';
- return SQLITE_CANTOPEN_BKPT;
}
- sqlcipher_sqlite3_snprintf(nOut-iOff, &zOut[iOff], "%s", zPath);
-
- /* Remove duplicate '/' characters. Except, two // at the beginning
- ** of a pathname is allowed since this is important on windows. */
- for(i=j=1; zOut[i]; i++){
- zOut[j++] = zOut[i];
- while( zOut[i]=='/' && zOut[i+1]=='/' ) i++;
+ if( pPath->nUsed + nName + 2 >= pPath->nOut ){
+ pPath->rc = SQLITE_ERROR;
+ return;
}
- zOut[j] = 0;
-
- assert( zOut[0]=='/' );
- for(i=j=0; zOut[i]; i++){
- if( zOut[i]=='/' ){
- /* Skip over internal "/." directory components */
- if( zOut[i+1]=='.' && zOut[i+2]=='/' ){
- i += 1;
- continue;
+ pPath->zOut[pPath->nUsed++] = '/';
+ memcpy(&pPath->zOut[pPath->nUsed], zName, nName);
+ pPath->nUsed += nName;
+#if defined(HAVE_READLINK) && defined(HAVE_LSTAT)
+ if( pPath->rc==SQLITE_OK ){
+ const char *zIn;
+ struct stat buf;
+ pPath->zOut[pPath->nUsed] = 0;
+ zIn = pPath->zOut;
+ if( osLstat(zIn, &buf)!=0 ){
+ if( errno!=ENOENT ){
+ pPath->rc = unixLogError(SQLITE_CANTOPEN_BKPT, "lstat", zIn);
}
-
- /* If this is a "/.." directory component then back out the
- ** previous term of the directory if it is something other than "..".
- */
- if( zOut[i+1]=='.'
- && zOut[i+2]=='.'
- && zOut[i+3]=='/'
- && unixBackupDir(zOut, &j)
- ){
- i += 2;
- continue;
+ }else if( S_ISLNK(buf.st_mode) ){
+ ssize_t got;
+ char zLnk[SQLITE_MAX_PATHLEN+2];
+ if( pPath->nSymlink++ > SQLITE_MAX_SYMLINK ){
+ pPath->rc = SQLITE_CANTOPEN_BKPT;
+ return;
+ }
+ got = osReadlink(zIn, zLnk, sizeof(zLnk)-2);
+ if( got<=0 || got>=(ssize_t)sizeof(zLnk)-2 ){
+ pPath->rc = unixLogError(SQLITE_CANTOPEN_BKPT, "readlink", zIn);
+ return;
}
+ zLnk[got] = 0;
+ if( zLnk[0]=='/' ){
+ pPath->nUsed = 0;
+ }else{
+ pPath->nUsed -= nName + 1;
+ }
+ appendAllPathElements(pPath, zLnk);
}
- if( ALWAYS(j>=0) ) zOut[j] = zOut[i];
- j++;
}
- if( NEVER(j==0) ) zOut[j++] = '/';
- zOut[j] = 0;
- return SQLITE_OK;
+#endif
+}
+
+/*
+** Append all path elements in zPath to the DbPath under construction.
+*/
+static void appendAllPathElements(
+ DbPath *pPath, /* Path under construction, to which to append zName */
+ const char *zPath /* Path to append to pPath. Is zero-terminated */
+){
+ int i = 0;
+ int j = 0;
+ do{
+ while( zPath[i] && zPath[i]!='/' ){ i++; }
+ if( i>j ){
+ appendOnePathElement(pPath, &zPath[j], i-j);
+ }
+ j = i+1;
+ }while( zPath[i++] );
}
/*
@@ -45268,86 +42122,27 @@ static int unixFullPathname(
int nOut, /* Size of output buffer in bytes */
char *zOut /* Output buffer */
){
-#if !defined(HAVE_READLINK) || !defined(HAVE_LSTAT)
- return mkFullPathname(zPath, zOut, nOut);
-#else
- int rc = SQLITE_OK;
- int nByte;
- int nLink = 0; /* Number of symbolic links followed so far */
- const char *zIn = zPath; /* Input path for each iteration of loop */
- char *zDel = 0;
-
- assert( pVfs->mxPathname==MAX_PATHNAME );
+ DbPath path;
UNUSED_PARAMETER(pVfs);
-
- /* 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. This function could fail if, for example, the
- ** current working directory has been unlinked.
- */
- SimulateIOError( return SQLITE_ERROR );
-
- do {
-
- /* Call stat() on path zIn. Set bLink to true if the path is a symbolic
- ** link, or false otherwise. */
- int bLink = 0;
- struct stat buf;
- if( osLstat(zIn, &buf)!=0 ){
- if( errno!=ENOENT ){
- rc = unixLogError(SQLITE_CANTOPEN_BKPT, "lstat", zIn);
- }
- }else{
- bLink = S_ISLNK(buf.st_mode);
- }
-
- if( bLink ){
- nLink++;
- if( zDel==0 ){
- zDel = sqlcipher_sqlite3_malloc(nOut);
- if( zDel==0 ) rc = SQLITE_NOMEM_BKPT;
- }else if( nLink>=SQLITE_MAX_SYMLINKS ){
- rc = SQLITE_CANTOPEN_BKPT;
- }
-
- if( rc==SQLITE_OK ){
- nByte = osReadlink(zIn, zDel, nOut-1);
- if( nByte<0 ){
- rc = unixLogError(SQLITE_CANTOPEN_BKPT, "readlink", zIn);
- }else{
- if( zDel[0]!='/' ){
- int n;
- for(n = sqlcipher_sqlite3Strlen30(zIn); n>0 && zIn[n-1]!='/'; n--);
- if( nByte+n+1>nOut ){
- rc = SQLITE_CANTOPEN_BKPT;
- }else{
- memmove(&zDel[n], zDel, nByte+1);
- memcpy(zDel, zIn, n);
- nByte += n;
- }
- }
- zDel[nByte] = '\0';
- }
- }
-
- zIn = zDel;
- }
-
- assert( rc!=SQLITE_OK || zIn!=zOut || zIn[0]=='/' );
- if( rc==SQLITE_OK && zIn!=zOut ){
- rc = mkFullPathname(zIn, zOut, nOut);
+ path.rc = 0;
+ path.nUsed = 0;
+ path.nSymlink = 0;
+ path.nOut = nOut;
+ path.zOut = zOut;
+ if( zPath[0]!='/' ){
+ char zPwd[SQLITE_MAX_PATHLEN+2];
+ if( osGetcwd(zPwd, sizeof(zPwd)-2)==0 ){
+ return unixLogError(SQLITE_CANTOPEN_BKPT, "getcwd", zPath);
}
- if( bLink==0 ) break;
- zIn = zOut;
- }while( rc==SQLITE_OK );
-
- sqlcipher_sqlite3_free(zDel);
- if( rc==SQLITE_OK && nLink ) rc = SQLITE_OK_SYMLINK;
- return rc;
-#endif /* HAVE_READLINK && HAVE_LSTAT */
+ appendAllPathElements(&path, zPwd);
+ }
+ appendAllPathElements(&path, zPath);
+ zOut[path.nUsed] = 0;
+ if( path.rc || path.nUsed<2 ) return SQLITE_CANTOPEN_BKPT;
+ if( path.nSymlink ) return SQLITE_OK_SYMLINK;
+ return SQLITE_OK;
}
-
#ifndef SQLITE_OMIT_LOAD_EXTENSION
/*
** Interfaces for opening a shared library, finding entry points
@@ -46846,6 +43641,28 @@ SQLITE_API int sqlcipher_sqlite3_os_init(void){
sqlcipher_sqlite3_vfs_register(&aVfs[i], i==0);
}
unixBigLock = sqlcipher_sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
+
+#ifndef SQLITE_OMIT_WAL
+ /* Validate lock assumptions */
+ assert( SQLITE_SHM_NLOCK==8 ); /* Number of available locks */
+ assert( UNIX_SHM_BASE==120 ); /* Start of locking area */
+ /* Locks:
+ ** WRITE UNIX_SHM_BASE 120
+ ** CKPT UNIX_SHM_BASE+1 121
+ ** RECOVER UNIX_SHM_BASE+2 122
+ ** READ-0 UNIX_SHM_BASE+3 123
+ ** READ-1 UNIX_SHM_BASE+4 124
+ ** READ-2 UNIX_SHM_BASE+5 125
+ ** READ-3 UNIX_SHM_BASE+6 126
+ ** READ-4 UNIX_SHM_BASE+7 127
+ ** DMS UNIX_SHM_BASE+8 128
+ */
+ assert( UNIX_SHM_DMS==128 ); /* Byte offset of the deadman-switch */
+#endif
+
+ /* Initialize temp file dir array. */
+ unixTempFileInit();
+
return SQLITE_OK;
}
@@ -46885,205 +43702,7 @@ SQLITE_API int sqlcipher_sqlite3_os_end(void){
/*
** Include code that is common to all os_*.c files
*/
-/************** Include os_common.h in the middle of os_win.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
-
-/*
-** 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 and x86_64 class CPUs.
-*/
-#ifndef SQLITE_HWTIME_H
-#define SQLITE_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(__STRICT_ANSI__) && \
- (defined(__GNUC__) || defined(_MSC_VER)) && \
- (defined(i386) || defined(__i386__) || defined(_M_IX86))
-
- #if defined(__GNUC__)
-
- __inline__ sqlite_uint64 sqlcipher_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 sqlcipher_sqlite3Hwtime(void){
- __asm {
- rdtsc
- ret ; return value at EDX:EAX
- }
- }
-
- #endif
-
-#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__))
-
- __inline__ sqlite_uint64 sqlcipher_sqlite3Hwtime(void){
- unsigned long val;
- __asm__ __volatile__ ("rdtsc" : "=A" (val));
- return val;
- }
-
-#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__))
-
- __inline__ sqlite_uint64 sqlcipher_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
-
- /*
- ** asm() is needed for hardware timing support. Without asm(),
- ** disable the sqlcipher_sqlite3Hwtime() routine.
- **
- ** sqlcipher_sqlite3Hwtime() is only used for some obscure debugging
- ** and analysis configurations, not in any deliverable, so this
- ** should not be a great loss.
- */
-SQLITE_PRIVATE sqlite_uint64 sqlcipher_sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
-
-#endif
-
-#endif /* !defined(SQLITE_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=sqlcipher_sqlite3Hwtime()
-#define TIMER_END g_elapsed=sqlcipher_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.
-*/
-#if defined(SQLITE_TEST)
-SQLITE_API extern int sqlcipher_sqlite3_io_error_hit;
-SQLITE_API extern int sqlcipher_sqlite3_io_error_hardhit;
-SQLITE_API extern int sqlcipher_sqlite3_io_error_pending;
-SQLITE_API extern int sqlcipher_sqlite3_io_error_persist;
-SQLITE_API extern int sqlcipher_sqlite3_io_error_benign;
-SQLITE_API extern int sqlcipher_sqlite3_diskfull_pending;
-SQLITE_API extern int sqlcipher_sqlite3_diskfull;
-#define SimulateIOErrorBenign(X) sqlcipher_sqlite3_io_error_benign=(X)
-#define SimulateIOError(CODE) \
- if( (sqlcipher_sqlite3_io_error_persist && sqlcipher_sqlite3_io_error_hit) \
- || sqlcipher_sqlite3_io_error_pending-- == 1 ) \
- { local_ioerr(); CODE; }
-static void local_ioerr(){
- IOTRACE(("IOERR\n"));
- sqlcipher_sqlite3_io_error_hit++;
- if( !sqlcipher_sqlite3_io_error_benign ) sqlcipher_sqlite3_io_error_hardhit++;
-}
-#define SimulateDiskfullError(CODE) \
- if( sqlcipher_sqlite3_diskfull_pending ){ \
- if( sqlcipher_sqlite3_diskfull_pending == 1 ){ \
- local_ioerr(); \
- sqlcipher_sqlite3_diskfull = 1; \
- sqlcipher_sqlite3_io_error_hit = 1; \
- CODE; \
- }else{ \
- sqlcipher_sqlite3_diskfull_pending--; \
- } \
- }
-#else
-#define SimulateIOErrorBenign(X)
-#define SimulateIOError(A)
-#define SimulateDiskfullError(A)
-#endif /* defined(SQLITE_TEST) */
-
-/*
-** When testing, keep a count of the number of open files.
-*/
-#if defined(SQLITE_TEST)
-SQLITE_API extern int sqlcipher_sqlite3_open_file_count;
-#define OpenCounter(X) sqlcipher_sqlite3_open_file_count+=(X)
-#else
-#define OpenCounter(X)
-#endif /* defined(SQLITE_TEST) */
-
-#endif /* !defined(_OS_COMMON_H_) */
-
-/************** End of os_common.h *******************************************/
-/************** Continuing where we left off in os_win.c *********************/
+/* #include "os_common.h" */
/*
** Include the header file for the Windows VFS.
@@ -48983,10 +45602,12 @@ SQLITE_API int sqlcipher_sqlite3_win32_set_directory8(
const char *zValue /* New value for directory being set or reset */
){
char **ppDirectory = 0;
+ int rc;
#ifndef SQLITE_OMIT_AUTOINIT
- int rc = sqlcipher_sqlite3_initialize();
+ rc = sqlcipher_sqlite3_initialize();
if( rc ) return rc;
#endif
+ sqlcipher_sqlite3_mutex_enter(sqlcipher_sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
if( type==SQLITE_WIN32_DATA_DIRECTORY_TYPE ){
ppDirectory = &sqlcipher_sqlite3_data_directory;
}else if( type==SQLITE_WIN32_TEMP_DIRECTORY_TYPE ){
@@ -49001,14 +45622,19 @@ SQLITE_API int sqlcipher_sqlite3_win32_set_directory8(
if( zValue && zValue[0] ){
zCopy = sqlcipher_sqlite3_mprintf("%s", zValue);
if ( zCopy==0 ){
- return SQLITE_NOMEM_BKPT;
+ rc = SQLITE_NOMEM_BKPT;
+ goto set_directory8_done;
}
}
sqlcipher_sqlite3_free(*ppDirectory);
*ppDirectory = zCopy;
- return SQLITE_OK;
+ rc = SQLITE_OK;
+ }else{
+ rc = SQLITE_ERROR;
}
- return SQLITE_ERROR;
+set_directory8_done:
+ sqlcipher_sqlite3_mutex_leave(sqlcipher_sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
+ return rc;
}
/*
@@ -51135,10 +47761,14 @@ static int winShmLock(
winFile *pDbFd = (winFile*)fd; /* Connection holding shared memory */
winShm *p = pDbFd->pShm; /* The shared memory being locked */
winShm *pX; /* For looping over all siblings */
- winShmNode *pShmNode = p->pShmNode;
+ winShmNode *pShmNode;
int rc = SQLITE_OK; /* Result code */
u16 mask; /* Mask of locks to take or release */
+ if( p==0 ) return SQLITE_IOERR_SHMLOCK;
+ pShmNode = p->pShmNode;
+ if( NEVER(pShmNode==0) ) return SQLITE_IOERR_SHMLOCK;
+
assert( ofst>=0 && ofst+n<=SQLITE_SHM_NLOCK );
assert( n>=1 );
assert( flags==(SQLITE_SHM_LOCK | SQLITE_SHM_SHARED)
@@ -51779,6 +48409,18 @@ static int winMakeEndInDirSep(int nBuf, char *zBuf){
}
/*
+** If sqlcipher_sqlite3_temp_directory is not, take the mutex and return true.
+**
+** If sqlcipher_sqlite3_temp_directory is NULL, omit the mutex and return false.
+*/
+static int winTempDirDefined(void){
+ sqlcipher_sqlite3_mutex_enter(sqlcipher_sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
+ if( sqlcipher_sqlite3_temp_directory!=0 ) return 1;
+ sqlcipher_sqlite3_mutex_leave(sqlcipher_sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
+ return 0;
+}
+
+/*
** Create a temporary file name and store the resulting pointer into pzBuf.
** The pointer returned in pzBuf must be freed via sqlcipher_sqlite3_free().
*/
@@ -51814,20 +48456,23 @@ static int winGetTempname(sqlcipher_sqlite3_vfs *pVfs, char **pzBuf){
*/
nDir = nMax - (nPre + 15);
assert( nDir>0 );
- if( sqlcipher_sqlite3_temp_directory ){
+ if( winTempDirDefined() ){
int nDirLen = sqlcipher_sqlite3Strlen30(sqlcipher_sqlite3_temp_directory);
if( nDirLen>0 ){
if( !winIsDirSep(sqlcipher_sqlite3_temp_directory[nDirLen-1]) ){
nDirLen++;
}
if( nDirLen>nDir ){
+ sqlcipher_sqlite3_mutex_leave(sqlcipher_sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
sqlcipher_sqlite3_free(zBuf);
OSTRACE(("TEMP-FILENAME rc=SQLITE_ERROR\n"));
return winLogError(SQLITE_ERROR, 0, "winGetTempname1", 0);
}
sqlcipher_sqlite3_snprintf(nMax, zBuf, "%s", sqlcipher_sqlite3_temp_directory);
}
+ sqlcipher_sqlite3_mutex_leave(sqlcipher_sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
}
+
#if defined(__CYGWIN__)
else{
static const char *azDirs[] = {
@@ -52616,7 +49261,7 @@ static BOOL winIsVerbatimPathname(
** pathname into zOut[]. zOut[] will be at least pVfs->mxPathname
** bytes in size.
*/
-static int winFullPathname(
+static int winFullPathnameNoMutex(
sqlcipher_sqlite3_vfs *pVfs, /* Pointer to vfs object */
const char *zRelative, /* Possibly relative input path */
int nFull, /* Size of output buffer in bytes */
@@ -52795,6 +49440,19 @@ static int winFullPathname(
}
#endif
}
+static int winFullPathname(
+ sqlcipher_sqlite3_vfs *pVfs, /* Pointer to vfs object */
+ const char *zRelative, /* Possibly relative input path */
+ int nFull, /* Size of output buffer in bytes */
+ char *zFull /* Output buffer */
+){
+ int rc;
+ sqlcipher_sqlite3_mutex *pMutex = sqlcipher_sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR);
+ sqlcipher_sqlite3_mutex_enter(pMutex);
+ rc = winFullPathnameNoMutex(pVfs, zRelative, nFull, zFull);
+ sqlcipher_sqlite3_mutex_leave(pMutex);
+ return rc;
+}
#ifndef SQLITE_OMIT_LOAD_EXTENSION
/*
@@ -53239,32 +49897,89 @@ SQLITE_API int sqlcipher_sqlite3_os_end(void){
** sqlcipher_sqlite3_deserialize().
*/
/* #include "sqliteInt.h" */
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
/*
** Forward declaration of objects used by this utility
*/
typedef struct sqlcipher_sqlite3_vfs MemVfs;
typedef struct MemFile MemFile;
+typedef struct MemStore MemStore;
/* Access to a lower-level VFS that (might) implement dynamic loading,
** access to randomness, etc.
*/
#define ORIGVFS(p) ((sqlcipher_sqlite3_vfs*)((p)->pAppData))
-/* An open file */
-struct MemFile {
- sqlcipher_sqlite3_file base; /* IO methods */
+/* Storage for a memdb file.
+**
+** An memdb object can be shared or separate. Shared memdb objects can be
+** used by more than one database connection. Mutexes are used by shared
+** memdb objects to coordinate access. Separate memdb objects are only
+** connected to a single database connection and do not require additional
+** mutexes.
+**
+** Shared memdb objects have .zFName!=0 and .pMutex!=0. They are created
+** using "file:/name?vfs=memdb". The first character of the name must be
+** "/" or else the object will be a separate memdb object. All shared
+** memdb objects are stored in memdb_g.apMemStore[] in an arbitrary order.
+**
+** Separate memdb objects are created using a name that does not begin
+** with "/" or using sqlcipher_sqlite3_deserialize().
+**
+** Access rules for shared MemStore objects:
+**
+** * .zFName is initialized when the object is created and afterwards
+** is unchanged until the object is destroyed. So it can be accessed
+** at any time as long as we know the object is not being destroyed,
+** which means while either the SQLITE_MUTEX_STATIC_VFS1 or
+** .pMutex is held or the object is not part of memdb_g.apMemStore[].
+**
+** * Can .pMutex can only be changed while holding the
+** SQLITE_MUTEX_STATIC_VFS1 mutex or while the object is not part
+** of memdb_g.apMemStore[].
+**
+** * Other fields can only be changed while holding the .pMutex mutex
+** or when the .nRef is less than zero and the object is not part of
+** memdb_g.apMemStore[].
+**
+** * The .aData pointer has the added requirement that it can can only
+** be changed (for resizing) when nMmap is zero.
+**
+*/
+struct MemStore {
sqlcipher_sqlite3_int64 sz; /* Size of the file */
sqlcipher_sqlite3_int64 szAlloc; /* Space allocated to aData */
sqlcipher_sqlite3_int64 szMax; /* Maximum allowed size of the file */
unsigned char *aData; /* content of the file */
+ sqlcipher_sqlite3_mutex *pMutex; /* Used by shared stores only */
int nMmap; /* Number of memory mapped pages */
unsigned mFlags; /* Flags */
+ int nRdLock; /* Number of readers */
+ int nWrLock; /* Number of writers. (Always 0 or 1) */
+ int nRef; /* Number of users of this MemStore */
+ char *zFName; /* The filename for shared stores */
+};
+
+/* An open file */
+struct MemFile {
+ sqlcipher_sqlite3_file base; /* IO methods */
+ MemStore *pStore; /* The storage */
int eLock; /* Most recent lock against this file */
};
/*
+** File-scope variables for holding the memdb files that are accessible
+** to multiple database connections in separate threads.
+**
+** Must hold SQLITE_MUTEX_STATIC_VFS1 to access any part of this object.
+*/
+static struct MemFS {
+ int nMemStore; /* Number of shared MemStore objects */
+ MemStore **apMemStore; /* Array of all shared MemStore objects */
+} memdb_g;
+
+/*
** Methods for MemFile
*/
static int memdbClose(sqlcipher_sqlite3_file*);
@@ -53317,7 +50032,10 @@ static sqlcipher_sqlite3_vfs memdb_vfs = {
memdbSleep, /* xSleep */
0, /* memdbCurrentTime, */ /* xCurrentTime */
memdbGetLastError, /* xGetLastError */
- memdbCurrentTimeInt64 /* xCurrentTimeInt64 */
+ memdbCurrentTimeInt64, /* xCurrentTimeInt64 */
+ 0, /* xSetSystemCall */
+ 0, /* xGetSystemCall */
+ 0, /* xNextSystemCall */
};
static const sqlcipher_sqlite3_io_methods memdb_io_methods = {
@@ -53342,19 +50060,67 @@ static const sqlcipher_sqlite3_io_methods memdb_io_methods = {
memdbUnfetch /* xUnfetch */
};
+/*
+** Enter/leave the mutex on a MemStore
+*/
+#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE==0
+static void memdbEnter(MemStore *p){
+ UNUSED_PARAMETER(p);
+}
+static void memdbLeave(MemStore *p){
+ UNUSED_PARAMETER(p);
+}
+#else
+static void memdbEnter(MemStore *p){
+ sqlcipher_sqlite3_mutex_enter(p->pMutex);
+}
+static void memdbLeave(MemStore *p){
+ sqlcipher_sqlite3_mutex_leave(p->pMutex);
+}
+#endif
+
/*
** Close an memdb-file.
-**
-** The pData pointer is owned by the application, so there is nothing
-** to free. Unless the SQLITE_DESERIALIZE_FREEONCLOSE flag is set,
-** in which case we own the pData pointer and need to free it.
+** Free the underlying MemStore object when its refcount drops to zero
+** or less.
*/
static int memdbClose(sqlcipher_sqlite3_file *pFile){
- MemFile *p = (MemFile *)pFile;
- if( p->mFlags & SQLITE_DESERIALIZE_FREEONCLOSE ){
- sqlcipher_sqlite3_free(p->aData);
+ MemStore *p = ((MemFile*)pFile)->pStore;
+ if( p->zFName ){
+ int i;
+#ifndef SQLITE_MUTEX_OMIT
+ sqlcipher_sqlite3_mutex *pVfsMutex = sqlcipher_sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
+#endif
+ sqlcipher_sqlite3_mutex_enter(pVfsMutex);
+ for(i=0; ALWAYS(i<memdb_g.nMemStore); i++){
+ if( memdb_g.apMemStore[i]==p ){
+ memdbEnter(p);
+ if( p->nRef==1 ){
+ memdb_g.apMemStore[i] = memdb_g.apMemStore[--memdb_g.nMemStore];
+ if( memdb_g.nMemStore==0 ){
+ sqlcipher_sqlite3_free(memdb_g.apMemStore);
+ memdb_g.apMemStore = 0;
+ }
+ }
+ break;
+ }
+ }
+ sqlcipher_sqlite3_mutex_leave(pVfsMutex);
+ }else{
+ memdbEnter(p);
+ }
+ p->nRef--;
+ if( p->nRef<=0 ){
+ if( p->mFlags & SQLITE_DESERIALIZE_FREEONCLOSE ){
+ sqlcipher_sqlite3_free(p->aData);
+ }
+ memdbLeave(p);
+ sqlcipher_sqlite3_mutex_free(p->pMutex);
+ sqlcipher_sqlite3_free(p);
+ }else{
+ memdbLeave(p);
}
return SQLITE_OK;
}
@@ -53368,22 +50134,25 @@ static int memdbRead(
int iAmt,
sqlite_int64 iOfst
){
- MemFile *p = (MemFile *)pFile;
+ MemStore *p = ((MemFile*)pFile)->pStore;
+ memdbEnter(p);
if( iOfst+iAmt>p->sz ){
memset(zBuf, 0, iAmt);
if( iOfst<p->sz ) memcpy(zBuf, p->aData+iOfst, p->sz - iOfst);
+ memdbLeave(p);
return SQLITE_IOERR_SHORT_READ;
}
memcpy(zBuf, p->aData+iOfst, iAmt);
+ memdbLeave(p);
return SQLITE_OK;
}
/*
** Try to enlarge the memory allocation to hold at least sz bytes
*/
-static int memdbEnlarge(MemFile *p, sqlcipher_sqlite3_int64 newSz){
+static int memdbEnlarge(MemStore *p, sqlcipher_sqlite3_int64 newSz){
unsigned char *pNew;
- if( (p->mFlags & SQLITE_DESERIALIZE_RESIZEABLE)==0 || p->nMmap>0 ){
+ if( (p->mFlags & SQLITE_DESERIALIZE_RESIZEABLE)==0 || NEVER(p->nMmap>0) ){
return SQLITE_FULL;
}
if( newSz>p->szMax ){
@@ -53392,7 +50161,7 @@ static int memdbEnlarge(MemFile *p, sqlcipher_sqlite3_int64 newSz){
newSz *= 2;
if( newSz>p->szMax ) newSz = p->szMax;
pNew = sqlcipher_sqlite3Realloc(p->aData, newSz);
- if( pNew==0 ) return SQLITE_NOMEM;
+ if( pNew==0 ) return SQLITE_IOERR_NOMEM;
p->aData = pNew;
p->szAlloc = newSz;
return SQLITE_OK;
@@ -53407,19 +50176,27 @@ static int memdbWrite(
int iAmt,
sqlite_int64 iOfst
){
- MemFile *p = (MemFile *)pFile;
- if( NEVER(p->mFlags & SQLITE_DESERIALIZE_READONLY) ) return SQLITE_READONLY;
+ MemStore *p = ((MemFile*)pFile)->pStore;
+ memdbEnter(p);
+ if( NEVER(p->mFlags & SQLITE_DESERIALIZE_READONLY) ){
+ /* Can't happen: memdbLock() will return SQLITE_READONLY before
+ ** reaching this point */
+ memdbLeave(p);
+ return SQLITE_IOERR_WRITE;
+ }
if( iOfst+iAmt>p->sz ){
int rc;
if( iOfst+iAmt>p->szAlloc
&& (rc = memdbEnlarge(p, iOfst+iAmt))!=SQLITE_OK
){
+ memdbLeave(p);
return rc;
}
if( iOfst>p->sz ) memset(p->aData+p->sz, 0, iOfst-p->sz);
p->sz = iOfst+iAmt;
}
memcpy(p->aData+iOfst, z, iAmt);
+ memdbLeave(p);
return SQLITE_OK;
}
@@ -53431,16 +50208,25 @@ static int memdbWrite(
** the size of a file, never to increase the size.
*/
static int memdbTruncate(sqlcipher_sqlite3_file *pFile, sqlite_int64 size){
- MemFile *p = (MemFile *)pFile;
- if( NEVER(size>p->sz) ) return SQLITE_FULL;
- p->sz = size;
- return SQLITE_OK;
+ MemStore *p = ((MemFile*)pFile)->pStore;
+ int rc = SQLITE_OK;
+ memdbEnter(p);
+ if( size>p->sz ){
+ /* This can only happen with a corrupt wal mode db */
+ rc = SQLITE_CORRUPT;
+ }else{
+ p->sz = size;
+ }
+ memdbLeave(p);
+ return rc;
}
/*
** Sync an memdb-file.
*/
static int memdbSync(sqlcipher_sqlite3_file *pFile, int flags){
+ UNUSED_PARAMETER(pFile);
+ UNUSED_PARAMETER(flags);
return SQLITE_OK;
}
@@ -53448,8 +50234,10 @@ static int memdbSync(sqlcipher_sqlite3_file *pFile, int flags){
** Return the current file-size of an memdb-file.
*/
static int memdbFileSize(sqlcipher_sqlite3_file *pFile, sqlite_int64 *pSize){
- MemFile *p = (MemFile *)pFile;
+ MemStore *p = ((MemFile*)pFile)->pStore;
+ memdbEnter(p);
*pSize = p->sz;
+ memdbLeave(p);
return SQLITE_OK;
}
@@ -53457,19 +50245,48 @@ static int memdbFileSize(sqlcipher_sqlite3_file *pFile, sqlite_int64 *pSize){
** Lock an memdb-file.
*/
static int memdbLock(sqlcipher_sqlite3_file *pFile, int eLock){
- MemFile *p = (MemFile *)pFile;
- if( eLock>SQLITE_LOCK_SHARED
- && (p->mFlags & SQLITE_DESERIALIZE_READONLY)!=0
- ){
- return SQLITE_READONLY;
+ MemFile *pThis = (MemFile*)pFile;
+ MemStore *p = pThis->pStore;
+ int rc = SQLITE_OK;
+ if( eLock==pThis->eLock ) return SQLITE_OK;
+ memdbEnter(p);
+ if( eLock>SQLITE_LOCK_SHARED ){
+ if( p->mFlags & SQLITE_DESERIALIZE_READONLY ){
+ rc = SQLITE_READONLY;
+ }else if( pThis->eLock<=SQLITE_LOCK_SHARED ){
+ if( p->nWrLock ){
+ rc = SQLITE_BUSY;
+ }else{
+ p->nWrLock = 1;
+ }
+ }
+ }else if( eLock==SQLITE_LOCK_SHARED ){
+ if( pThis->eLock > SQLITE_LOCK_SHARED ){
+ assert( p->nWrLock==1 );
+ p->nWrLock = 0;
+ }else if( p->nWrLock ){
+ rc = SQLITE_BUSY;
+ }else{
+ p->nRdLock++;
+ }
+ }else{
+ assert( eLock==SQLITE_LOCK_NONE );
+ if( pThis->eLock>SQLITE_LOCK_SHARED ){
+ assert( p->nWrLock==1 );
+ p->nWrLock = 0;
+ }
+ assert( p->nRdLock>0 );
+ p->nRdLock--;
}
- p->eLock = eLock;
- return SQLITE_OK;
+ if( rc==SQLITE_OK ) pThis->eLock = eLock;
+ memdbLeave(p);
+ return rc;
}
-#if 0 /* Never used because memdbAccess() always returns false */
+#if 0
/*
-** Check if another file-handle holds a RESERVED lock on an memdb-file.
+** This interface is only used for crash recovery, which does not
+** occur on an in-memory database.
*/
static int memdbCheckReservedLock(sqlcipher_sqlite3_file *pFile, int *pResOut){
*pResOut = 0;
@@ -53477,12 +50294,14 @@ static int memdbCheckReservedLock(sqlcipher_sqlite3_file *pFile, int *pResOut){
}
#endif
+
/*
** File control method. For custom operations on an memdb-file.
*/
static int memdbFileControl(sqlcipher_sqlite3_file *pFile, int op, void *pArg){
- MemFile *p = (MemFile *)pFile;
+ MemStore *p = ((MemFile*)pFile)->pStore;
int rc = SQLITE_NOTFOUND;
+ memdbEnter(p);
if( op==SQLITE_FCNTL_VFSNAME ){
*(char**)pArg = sqlcipher_sqlite3_mprintf("memdb(%p,%lld)", p->aData, p->sz);
rc = SQLITE_OK;
@@ -53500,6 +50319,7 @@ static int memdbFileControl(sqlcipher_sqlite3_file *pFile, int op, void *pArg){
*(sqlcipher_sqlite3_int64*)pArg = iLimit;
rc = SQLITE_OK;
}
+ memdbLeave(p);
return rc;
}
@@ -53516,6 +50336,7 @@ static int memdbSectorSize(sqlcipher_sqlite3_file *pFile){
** Return the device characteristic flags supported by an memdb-file.
*/
static int memdbDeviceCharacteristics(sqlcipher_sqlite3_file *pFile){
+ UNUSED_PARAMETER(pFile);
return SQLITE_IOCAP_ATOMIC |
SQLITE_IOCAP_POWERSAFE_OVERWRITE |
SQLITE_IOCAP_SAFE_APPEND |
@@ -53529,20 +50350,26 @@ static int memdbFetch(
int iAmt,
void **pp
){
- MemFile *p = (MemFile *)pFile;
- if( iOfst+iAmt>p->sz ){
+ MemStore *p = ((MemFile*)pFile)->pStore;
+ memdbEnter(p);
+ if( iOfst+iAmt>p->sz || (p->mFlags & SQLITE_DESERIALIZE_RESIZEABLE)!=0 ){
*pp = 0;
}else{
p->nMmap++;
*pp = (void*)(p->aData + iOfst);
}
+ memdbLeave(p);
return SQLITE_OK;
}
/* Release a memory-mapped page */
static int memdbUnfetch(sqlcipher_sqlite3_file *pFile, sqlcipher_sqlite3_int64 iOfst, void *pPage){
- MemFile *p = (MemFile *)pFile;
+ MemStore *p = ((MemFile*)pFile)->pStore;
+ UNUSED_PARAMETER(iOfst);
+ UNUSED_PARAMETER(pPage);
+ memdbEnter(p);
p->nMmap--;
+ memdbLeave(p);
return SQLITE_OK;
}
@@ -53552,20 +50379,79 @@ static int memdbUnfetch(sqlcipher_sqlite3_file *pFile, sqlcipher_sqlite3_int64 i
static int memdbOpen(
sqlcipher_sqlite3_vfs *pVfs,
const char *zName,
- sqlcipher_sqlite3_file *pFile,
+ sqlcipher_sqlite3_file *pFd,
int flags,
int *pOutFlags
){
- MemFile *p = (MemFile*)pFile;
- if( (flags & SQLITE_OPEN_MAIN_DB)==0 ){
- return ORIGVFS(pVfs)->xOpen(ORIGVFS(pVfs), zName, pFile, flags, pOutFlags);
+ MemFile *pFile = (MemFile*)pFd;
+ MemStore *p = 0;
+ int szName;
+ UNUSED_PARAMETER(pVfs);
+
+ memset(pFile, 0, sizeof(*pFile));
+ szName = sqlcipher_sqlite3Strlen30(zName);
+ if( szName>1 && zName[0]=='/' ){
+ int i;
+#ifndef SQLITE_MUTEX_OMIT
+ sqlcipher_sqlite3_mutex *pVfsMutex = sqlcipher_sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
+#endif
+ sqlcipher_sqlite3_mutex_enter(pVfsMutex);
+ for(i=0; i<memdb_g.nMemStore; i++){
+ if( strcmp(memdb_g.apMemStore[i]->zFName,zName)==0 ){
+ p = memdb_g.apMemStore[i];
+ break;
+ }
+ }
+ if( p==0 ){
+ MemStore **apNew;
+ p = sqlcipher_sqlite3Malloc( sizeof(*p) + szName + 3 );
+ if( p==0 ){
+ sqlcipher_sqlite3_mutex_leave(pVfsMutex);
+ return SQLITE_NOMEM;
+ }
+ apNew = sqlcipher_sqlite3Realloc(memdb_g.apMemStore,
+ sizeof(apNew[0])*(memdb_g.nMemStore+1) );
+ if( apNew==0 ){
+ sqlcipher_sqlite3_free(p);
+ sqlcipher_sqlite3_mutex_leave(pVfsMutex);
+ return SQLITE_NOMEM;
+ }
+ apNew[memdb_g.nMemStore++] = p;
+ memdb_g.apMemStore = apNew;
+ memset(p, 0, sizeof(*p));
+ p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE|SQLITE_DESERIALIZE_FREEONCLOSE;
+ p->szMax = sqlcipher_sqlite3GlobalConfig.mxMemdbSize;
+ p->zFName = (char*)&p[1];
+ memcpy(p->zFName, zName, szName+1);
+ p->pMutex = sqlcipher_sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
+ if( p->pMutex==0 ){
+ memdb_g.nMemStore--;
+ sqlcipher_sqlite3_free(p);
+ sqlcipher_sqlite3_mutex_leave(pVfsMutex);
+ return SQLITE_NOMEM;
+ }
+ p->nRef = 1;
+ memdbEnter(p);
+ }else{
+ memdbEnter(p);
+ p->nRef++;
+ }
+ sqlcipher_sqlite3_mutex_leave(pVfsMutex);
+ }else{
+ p = sqlcipher_sqlite3Malloc( sizeof(*p) );
+ if( p==0 ){
+ return SQLITE_NOMEM;
+ }
+ memset(p, 0, sizeof(*p));
+ p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE | SQLITE_DESERIALIZE_FREEONCLOSE;
+ p->szMax = sqlcipher_sqlite3GlobalConfig.mxMemdbSize;
}
- memset(p, 0, sizeof(*p));
- p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE | SQLITE_DESERIALIZE_FREEONCLOSE;
- assert( pOutFlags!=0 ); /* True because flags==SQLITE_OPEN_MAIN_DB */
- *pOutFlags = flags | SQLITE_OPEN_MEMORY;
- pFile->pMethods = &memdb_io_methods;
- p->szMax = sqlcipher_sqlite3GlobalConfig.mxMemdbSize;
+ pFile->pStore = p;
+ if( pOutFlags!=0 ){
+ *pOutFlags = flags | SQLITE_OPEN_MEMORY;
+ }
+ pFd->pMethods = &memdb_io_methods;
+ memdbLeave(p);
return SQLITE_OK;
}
@@ -53593,6 +50479,9 @@ static int memdbAccess(
int flags,
int *pResOut
){
+ UNUSED_PARAMETER(pVfs);
+ UNUSED_PARAMETER(zPath);
+ UNUSED_PARAMETER(flags);
*pResOut = 0;
return SQLITE_OK;
}
@@ -53608,6 +50497,7 @@ static int memdbFullPathname(
int nOut,
char *zOut
){
+ UNUSED_PARAMETER(pVfs);
sqlcipher_sqlite3_snprintf(nOut, zOut, "%s", zPath);
return SQLITE_OK;
}
@@ -53680,9 +50570,14 @@ static int memdbCurrentTimeInt64(sqlcipher_sqlite3_vfs *pVfs, sqlcipher_sqlite3_
*/
static MemFile *memdbFromDbSchema(sqlcipher_sqlite3 *db, const char *zSchema){
MemFile *p = 0;
+ MemStore *pStore;
int rc = sqlcipher_sqlite3_file_control(db, zSchema, SQLITE_FCNTL_FILE_POINTER, &p);
if( rc ) return 0;
if( p->base.pMethods!=&memdb_io_methods ) return 0;
+ pStore = p->pStore;
+ memdbEnter(pStore);
+ if( pStore->zFName!=0 ) p = 0;
+ memdbLeave(pStore);
return p;
}
@@ -53718,12 +50613,14 @@ SQLITE_API unsigned char *sqlcipher_sqlite3_serialize(
if( piSize ) *piSize = -1;
if( iDb<0 ) return 0;
if( p ){
- if( piSize ) *piSize = p->sz;
+ MemStore *pStore = p->pStore;
+ assert( pStore->pMutex==0 );
+ if( piSize ) *piSize = pStore->sz;
if( mFlags & SQLITE_SERIALIZE_NOCOPY ){
- pOut = p->aData;
+ pOut = pStore->aData;
}else{
- pOut = sqlcipher_sqlite3_malloc64( p->sz );
- if( pOut ) memcpy(pOut, p->aData, p->sz);
+ pOut = sqlcipher_sqlite3_malloc64( pStore->sz );
+ if( pOut ) memcpy(pOut, pStore->aData, pStore->sz);
}
return pOut;
}
@@ -53793,7 +50690,8 @@ SQLITE_API int sqlcipher_sqlite3_deserialize(
sqlcipher_sqlite3_mutex_enter(db->mutex);
if( zSchema==0 ) zSchema = db->aDb[0].zDbSName;
iDb = sqlcipher_sqlite3FindDbName(db, zSchema);
- if( iDb<0 ){
+ testcase( iDb==1 );
+ if( iDb<2 && iDb!=0 ){
rc = SQLITE_ERROR;
goto end_deserialize;
}
@@ -53817,15 +50715,16 @@ SQLITE_API int sqlcipher_sqlite3_deserialize(
if( p==0 ){
rc = SQLITE_ERROR;
}else{
- p->aData = pData;
+ MemStore *pStore = p->pStore;
+ pStore->aData = pData;
pData = 0;
- p->sz = szDb;
- p->szAlloc = szBuf;
- p->szMax = szBuf;
- if( p->szMax<sqlcipher_sqlite3GlobalConfig.mxMemdbSize ){
- p->szMax = sqlcipher_sqlite3GlobalConfig.mxMemdbSize;
+ pStore->sz = szDb;
+ pStore->szAlloc = szBuf;
+ pStore->szMax = szBuf;
+ if( pStore->szMax<sqlcipher_sqlite3GlobalConfig.mxMemdbSize ){
+ pStore->szMax = sqlcipher_sqlite3GlobalConfig.mxMemdbSize;
}
- p->mFlags = mFlags;
+ pStore->mFlags = mFlags;
rc = SQLITE_OK;
}
@@ -53844,7 +50743,9 @@ end_deserialize:
*/
SQLITE_PRIVATE int sqlcipher_sqlite3MemdbInit(void){
sqlcipher_sqlite3_vfs *pLower = sqlcipher_sqlite3_vfs_find(0);
- int sz = pLower->szOsFile;
+ unsigned int sz;
+ if( NEVER(pLower==0) ) return SQLITE_ERROR;
+ sz = pLower->szOsFile;
memdb_vfs.pAppData = pLower;
/* The following conditional can only be true when compiled for
** Windows x86 and SQLITE_MAX_MMAP_SIZE=0. We always leave
@@ -53854,7 +50755,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3MemdbInit(void){
memdb_vfs.szOsFile = sz;
return sqlcipher_sqlite3_vfs_register(&memdb_vfs, 0);
}
-#endif /* SQLITE_ENABLE_DESERIALIZE */
+#endif /* SQLITE_OMIT_DESERIALIZE */
/************** End of memdb.c ***********************************************/
/************** Begin file bitvec.c ******************************************/
@@ -54213,7 +51114,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3BitvecBuiltinTest(int sz, int *aOp){
sqlcipher_sqlite3BitvecClear(0, 1, pTmpSpace);
/* Run the program */
- pc = 0;
+ pc = i = 0;
while( (op = aOp[pc])!=0 ){
switch( op ){
case 1:
@@ -54517,11 +51418,14 @@ static int numberOfCachePages(PCache *p){
** suggested cache size is set to N. */
return p->szCache;
}else{
+ i64 n;
/* IMPLEMANTATION-OF: R-59858-46238 If the argument N is negative, then the
** number of cache pages is adjusted to be a number of pages that would
** use approximately abs(N*1024) bytes of memory based on the current
** page size. */
- return (int)((-1024*(i64)p->szCache)/(p->szPage+p->szExtra));
+ n = ((-1024*(i64)p->szCache)/(p->szPage+p->szExtra));
+ if( n>1000000000 ) n = 1000000000;
+ return (int)n;
}
}
@@ -54893,14 +51797,24 @@ SQLITE_PRIVATE void sqlcipher_sqlite3PcacheClearSyncFlags(PCache *pCache){
*/
SQLITE_PRIVATE void sqlcipher_sqlite3PcacheMove(PgHdr *p, Pgno newPgno){
PCache *pCache = p->pCache;
+ sqlcipher_sqlite3_pcache_page *pOther;
assert( p->nRef>0 );
assert( newPgno>0 );
assert( sqlcipher_sqlite3PcachePageSanity(p) );
pcacheTrace(("%p.MOVE %d -> %d\n",pCache,p->pgno,newPgno));
+ pOther = sqlcipher_sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, newPgno, 0);
+ if( pOther ){
+ PgHdr *pXPage = (PgHdr*)pOther->pExtra;
+ assert( pXPage->nRef==0 );
+ pXPage->nRef++;
+ pCache->nRefSum++;
+ sqlcipher_sqlite3PcacheDrop(pXPage);
+ }
sqlcipher_sqlite3GlobalConfig.pcache2.xRekey(pCache->pCache, p->pPage, p->pgno,newPgno);
p->pgno = newPgno;
if( (p->flags&PGHDR_DIRTY) && (p->flags&PGHDR_NEED_SYNC) ){
pcacheManageDirtyList(p, PCACHE_DIRTYLIST_FRONT);
+ assert( sqlcipher_sqlite3PcachePageSanity(p) );
}
}
@@ -55620,6 +52534,7 @@ static PgHdr1 *pcache1AllocPage(PCache1 *pCache, int benignMalloc){
p->page.pExtra = &p[1];
p->isBulkLocal = 0;
p->isAnchor = 0;
+ p->pLruPrev = 0; /* Initializing this saves a valgrind error */
}
(*pCache->pnPurgeable)++;
return p;
@@ -55975,12 +52890,18 @@ static sqlcipher_sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPur
*/
static void pcache1Cachesize(sqlcipher_sqlite3_pcache *p, int nMax){
PCache1 *pCache = (PCache1 *)p;
+ u32 n;
+ assert( nMax>=0 );
if( pCache->bPurgeable ){
PGroup *pGroup = pCache->pGroup;
pcache1EnterMutex(pGroup);
- pGroup->nMaxPage += (nMax - pCache->nMax);
+ n = (u32)nMax;
+ if( n > 0x7fff0000 - pGroup->nMaxPage + pCache->nMax ){
+ n = 0x7fff0000 - pGroup->nMaxPage + pCache->nMax;
+ }
+ pGroup->nMaxPage += (n - pCache->nMax);
pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
- pCache->nMax = nMax;
+ pCache->nMax = n;
pCache->n90pct = pCache->nMax*9/10;
pcache1EnforceMaxPage(pCache);
pcache1LeaveMutex(pGroup);
@@ -55996,7 +52917,7 @@ static void pcache1Shrink(sqlcipher_sqlite3_pcache *p){
PCache1 *pCache = (PCache1*)p;
if( pCache->bPurgeable ){
PGroup *pGroup = pCache->pGroup;
- int savedMaxPage;
+ unsigned int savedMaxPage;
pcache1EnterMutex(pGroup);
savedMaxPage = pGroup->nMaxPage;
pGroup->nMaxPage = 0;
@@ -56275,23 +53196,26 @@ static void pcache1Rekey(
PCache1 *pCache = (PCache1 *)p;
PgHdr1 *pPage = (PgHdr1 *)pPg;
PgHdr1 **pp;
- unsigned int h;
+ unsigned int hOld, hNew;
assert( pPage->iKey==iOld );
assert( pPage->pCache==pCache );
+ assert( iOld!=iNew ); /* The page number really is changing */
pcache1EnterMutex(pCache->pGroup);
- h = iOld%pCache->nHash;
- pp = &pCache->apHash[h];
+ assert( pcache1FetchNoMutex(p, iOld, 0)==pPage ); /* pPg really is iOld */
+ hOld = iOld%pCache->nHash;
+ pp = &pCache->apHash[hOld];
while( (*pp)!=pPage ){
pp = &(*pp)->pNext;
}
*pp = pPage->pNext;
- h = iNew%pCache->nHash;
+ assert( pcache1FetchNoMutex(p, iNew, 0)==0 ); /* iNew not in cache */
+ hNew = iNew%pCache->nHash;
pPage->iKey = iNew;
- pPage->pNext = pCache->apHash[h];
- pCache->apHash[h] = pPage;
+ pPage->pNext = pCache->apHash[hNew];
+ pCache->apHash[hNew] = pPage;
if( iNew>pCache->iMaxKey ){
pCache->iMaxKey = iNew;
}
@@ -57554,6 +54478,7 @@ struct PagerSavepoint {
Bitvec *pInSavepoint; /* Set of pages in this savepoint */
Pgno nOrig; /* Original number of pages in file */
Pgno iSubRec; /* Index of first record in sub-journal */
+ int bTruncateOnRelease; /* If stmt journal may be truncated on RELEASE */
#ifndef SQLITE_OMIT_WAL
u32 aWalData[WAL_SAVEPOINT_NDATA]; /* WAL savepoint context */
#endif
@@ -57748,6 +54673,7 @@ struct Pager {
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 */
+ u8 memVfs; /* VFS-implemented memory database */
/**************************************************************************
** The following block contains those class members that change during
@@ -57797,8 +54723,9 @@ struct Pager {
i16 nReserve; /* Number of unused bytes at end of each page */
u32 vfsFlags; /* Flags for sqlcipher_sqlite3_vfs.xOpen() */
u32 sectorSize; /* Assumed sector size during rollback */
- int pageSize; /* Number of bytes in a page */
Pgno mxPgno; /* Maximum allowed size of the database */
+ Pgno lckPgno; /* Page number for the locking page */
+ i64 pageSize; /* Number of bytes in a page */
i64 journalSizeLimit; /* Size limit for persistent journal files */
char *zFilename; /* Name of the database file */
char *zJournal; /* Name of the journal file */
@@ -58208,6 +55135,9 @@ static int subjRequiresPage(PgHdr *pPg){
for(i=0; i<pPager->nSavepoint; i++){
p = &pPager->aSavepoint[i];
if( p->nOrig>=pgno && 0==sqlcipher_sqlite3BitvecTestNotNull(p->pInSavepoint, pgno) ){
+ for(i=i+1; i<pPager->nSavepoint; i++){
+ pPager->aSavepoint[i].bTruncateOnRelease = 0;
+ }
return 1;
}
}
@@ -58800,7 +55730,7 @@ static int readJournalHdr(
** journal file descriptor is advanced to the next sector boundary before
** anything is written. The format is:
**
-** + 4 bytes: PAGER_MJ_PGNO.
+** + 4 bytes: PAGER_SJ_PGNO.
** + N bytes: super-journal filename in utf-8.
** + 4 bytes: N (length of super-journal name in bytes, no nul-terminator).
** + 4 bytes: super-journal name checksum.
@@ -58848,7 +55778,7 @@ static int writeSuperJournal(Pager *pPager, const char *zSuper){
/* Write the super-journal data to the end of the journal file. If
** an error occurs, return the error code to the caller.
*/
- if( (0 != (rc = write32bits(pPager->jfd, iHdrOff, PAGER_MJ_PGNO(pPager))))
+ if( (0 != (rc = write32bits(pPager->jfd, iHdrOff, PAGER_SJ_PGNO(pPager))))
|| (0 != (rc = sqlcipher_sqlite3OsWrite(pPager->jfd, zSuper, nSuper, iHdrOff+4)))
|| (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nSuper, nSuper)))
|| (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nSuper+4, cksum)))
@@ -59391,7 +56321,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3PagerAlignReserve(Pager *pDest, Pager *pSrc
** corrupted, SQLITE_DONE is returned. Data is considered corrupted in
** two circumstances:
**
-** * If the record page-number is illegal (0 or PAGER_MJ_PGNO), or
+** * If the record page-number is illegal (0 or PAGER_SJ_PGNO), or
** * If the record is being rolled back from the main journal file
** and the checksum field does not match the record content.
**
@@ -59458,7 +56388,7 @@ static int pager_playback_one_page(
** it could cause invalid data to be written into the journal. We need to
** detect this invalid data (with high probability) and ignore it.
*/
- if( pgno==0 || pgno==PAGER_MJ_PGNO(pPager) ){
+ if( pgno==0 || pgno==PAGER_SJ_PGNO(pPager) ){
assert( !isSavepnt );
return SQLITE_DONE;
}
@@ -59821,6 +56751,7 @@ static int pager_truncate(Pager *pPager, Pgno nPage){
memset(pTmp, 0, szPage);
testcase( (newSize-szPage) == currentSize );
testcase( (newSize-szPage) > currentSize );
+ sqlcipher_sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_SIZE_HINT, &newSize);
rc = sqlcipher_sqlite3OsWrite(pPager->fd, pTmp, szPage, newSize-szPage);
}
if( rc==SQLITE_OK ){
@@ -60043,6 +56974,9 @@ static int pager_playback(Pager *pPager, int isHot){
goto end_playback;
}
pPager->dbSize = mxPg;
+ if( pPager->mxPgno<mxPg ){
+ pPager->mxPgno = mxPg;
+ }
}
/* Copy original pages out of the journal and back into the
@@ -60226,6 +57160,7 @@ static int readDbPage(PgHdr *pPg){
*/
static void pager_write_changecounter(PgHdr *pPg){
u32 change_counter;
+ if( NEVER(pPg==0) ) return;
/* Increment the value just read and write it back to byte 24. */
change_counter = sqlcipher_sqlite3Get4byte((u8*)pPg->pPager->dbFileVers)+1;
@@ -60940,6 +57875,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3PagerSetPagesize(Pager *pPager, u32 *pPageSi
pPager->pTmpSpace = pNew;
pPager->dbSize = (Pgno)((nByte+pageSize-1)/pageSize);
pPager->pageSize = pageSize;
+ pPager->lckPgno = (Pgno)(PENDING_BYTE/pageSize) + 1;
}else{
sqlcipher_sqlite3PageFree(pNew);
}
@@ -61101,8 +58037,7 @@ static int pager_wait_on_lock(Pager *pPager, int locktype){
** current database image, in pages, OR
**
** b) if the page content were written at this time, it would not
-** be necessary to write the current content out to the sub-journal
-** (as determined by function subjRequiresPage()).
+** be necessary to write the current content out to the sub-journal.
**
** If the condition asserted by this function were not true, and the
** dirty page were to be discarded from the cache via the pagerStress()
@@ -61117,8 +58052,16 @@ static int pager_wait_on_lock(Pager *pPager, int locktype){
*/
#if defined(SQLITE_DEBUG)
static void assertTruncateConstraintCb(PgHdr *pPg){
+ Pager *pPager = pPg->pPager;
assert( pPg->flags&PGHDR_DIRTY );
- assert( !subjRequiresPage(pPg) || pPg->pgno<=pPg->pPager->dbSize );
+ if( pPg->pgno>pPager->dbSize ){ /* if (a) is false */
+ Pgno pgno = pPg->pgno;
+ int i;
+ for(i=0; i<pPg->pPager->nSavepoint; i++){
+ PagerSavepoint *p = &pPager->aSavepoint[i];
+ assert( p->nOrig<pgno || sqlcipher_sqlite3BitvecTestNotNull(p->pInSavepoint,pgno) );
+ }
+ }
}
static void assertTruncateConstraint(Pager *pPager){
sqlcipher_sqlite3PcacheIterateDirty(pPager->pPCache, assertTruncateConstraintCb);
@@ -61139,7 +58082,7 @@ static void assertTruncateConstraint(Pager *pPager){
** then continue writing to the database.
*/
SQLITE_PRIVATE void sqlcipher_sqlite3PagerTruncateImage(Pager *pPager, Pgno nPage){
- assert( pPager->dbSize>=nPage );
+ assert( pPager->dbSize>=nPage || CORRUPT_DB );
assert( pPager->eState>=PAGER_WRITER_CACHEMOD );
pPager->dbSize = nPage;
@@ -61883,7 +58826,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3PagerOpen(
int rc = SQLITE_OK; /* Return code */
int tempFile = 0; /* True for temp files (incl. in-memory files) */
int memDb = 0; /* True if this is an in-memory file */
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
int memJM = 0; /* Memory journal mode */
#else
# define memJM 0
@@ -62076,6 +59019,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3PagerOpen(
pPager->zWal = 0;
}
#endif
+ (void)pPtr; /* Suppress warning about unused pPtr value */
if( nPathname ) sqlcipher_sqlite3DbFree(0, zPathname);
pPager->pVfs = pVfs;
@@ -62087,8 +59031,8 @@ SQLITE_PRIVATE int sqlcipher_sqlite3PagerOpen(
int fout = 0; /* VFS flags returned by xOpen() */
rc = sqlcipher_sqlite3OsOpen(pVfs, pPager->zFilename, pPager->fd, vfsFlags, &fout);
assert( !memDb );
-#ifdef SQLITE_ENABLE_DESERIALIZE
- memJM = (fout&SQLITE_OPEN_MEMORY)!=0;
+#ifndef SQLITE_OMIT_DESERIALIZE
+ pPager->memVfs = memJM = (fout&SQLITE_OPEN_MEMORY)!=0;
#endif
readOnly = (fout&SQLITE_OPEN_READONLY)!=0;
@@ -62473,7 +59417,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3PagerSharedLock(Pager *pPager){
** may mean that the pager was in the error-state when this
** function was called and the journal file does not exist.
*/
- if( !isOpen(pPager->jfd) ){
+ if( !isOpen(pPager->jfd) && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){
sqlcipher_sqlite3_vfs * const pVfs = pPager->pVfs;
int bExists; /* True if journal file exists */
rc = sqlcipher_sqlite3OsAccess(
@@ -62718,7 +59662,7 @@ static int getPageNormal(
if( pPg->pPager && !noContent ){
/* In this case the pcache already contains an initialized copy of
** the page. Return without further ado. */
- assert( pgno!=PAGER_MJ_PGNO(pPager) );
+ assert( pgno!=PAGER_SJ_PGNO(pPager) );
pPager->aStat[PAGER_STAT_HIT]++;
return SQLITE_OK;
@@ -62729,7 +59673,7 @@ static int getPageNormal(
** (*) obsolete. Was: maximum page number is 2^31
** (2) Never try to fetch the locking page
*/
- if( pgno==PAGER_MJ_PGNO(pPager) ){
+ if( pgno==PAGER_SJ_PGNO(pPager) ){
rc = SQLITE_CORRUPT_BKPT;
goto pager_acquire_err;
}
@@ -62880,6 +59824,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3PagerGet(
DbPage **ppPage, /* Write a pointer to the page here */
int flags /* PAGER_GET_XXX flags */
){
+ /* printf("PAGE %u\n", pgno); fflush(stdout); */
return pPager->xGet(pPager, pgno, ppPage, flags);
}
@@ -63028,6 +59973,7 @@ static int pager_open_journal(Pager *pPager){
if( rc!=SQLITE_OK ){
sqlcipher_sqlite3BitvecDestroy(pPager->pInJournal);
pPager->pInJournal = 0;
+ pPager->journalOff = 0;
}else{
assert( pPager->eState==PAGER_WRITER_LOCKED );
pPager->eState = PAGER_WRITER_CACHEMOD;
@@ -63060,7 +60006,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3PagerBegin(Pager *pPager, int exFlag, int su
assert( pPager->eState>=PAGER_READER && pPager->eState<PAGER_ERROR );
pPager->subjInMemory = (u8)subjInMemory;
- if( ALWAYS(pPager->eState==PAGER_READER) ){
+ if( pPager->eState==PAGER_READER ){
assert( pPager->pInJournal==0 );
if( pagerUseWal(pPager) ){
@@ -63132,7 +60078,7 @@ static SQLITE_NOINLINE int pagerAddPageToRollbackJournal(PgHdr *pPg){
/* We should never write to the journal file the page that
** contains the database locks. The following assert verifies
** that we do not. */
- assert( pPg->pgno!=PAGER_MJ_PGNO(pPager) );
+ assert( pPg->pgno!=PAGER_SJ_PGNO(pPager) );
assert( pPager->journalHdr<=pPager->journalOff );
CODEC2(pPager, pPg->pData, pPg->pgno, 7, return SQLITE_NOMEM_BKPT, pData2);
@@ -63311,7 +60257,7 @@ static SQLITE_NOINLINE int pagerWriteLargeSector(PgHdr *pPg){
Pgno pg = pg1+ii;
PgHdr *pPage;
if( pg==pPg->pgno || !sqlcipher_sqlite3BitvecTest(pPager->pInJournal, pg) ){
- if( pg!=PAGER_MJ_PGNO(pPager) ){
+ if( pg!=PAGER_SJ_PGNO(pPager) ){
rc = sqlcipher_sqlite3PagerGet(pPager, pg, &pPage, 0);
if( rc==SQLITE_OK ){
rc = pager_write(pPage);
@@ -63789,7 +60735,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3PagerCommitPhaseOne(
** last page is never written out to disk, leaving the database file
** undersized. Fix this now if it is the case. */
if( pPager->dbSize>pPager->dbFileSize ){
- Pgno nNew = pPager->dbSize - (pPager->dbSize==PAGER_MJ_PGNO(pPager));
+ Pgno nNew = pPager->dbSize - (pPager->dbSize==PAGER_SJ_PGNO(pPager));
assert( pPager->eState==PAGER_WRITER_DBMOD );
rc = pager_truncate(pPager, nNew);
if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
@@ -63960,8 +60906,8 @@ SQLITE_PRIVATE int sqlcipher_sqlite3PagerRefcount(Pager *pPager){
** used by the pager and its associated cache.
*/
SQLITE_PRIVATE int sqlcipher_sqlite3PagerMemUsed(Pager *pPager){
- int perPageSize = pPager->pageSize + pPager->nExtra + sizeof(PgHdr)
- + 5*sizeof(void*);
+ int perPageSize = pPager->pageSize + pPager->nExtra
+ + (int)(sizeof(PgHdr) + 5*sizeof(void*));
return perPageSize*sqlcipher_sqlite3PcachePagecount(pPager->pPCache)
+ sqlcipher_sqlite3MallocSize(pPager)
+ pPager->pageSize;
@@ -64030,7 +60976,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3PagerCacheStat(Pager *pPager, int eStat, in
** Return true if this is an in-memory or temp-file backed pager.
*/
SQLITE_PRIVATE int sqlcipher_sqlite3PagerIsMemdb(Pager *pPager){
- return pPager->tempFile;
+ return pPager->tempFile || pPager->memVfs;
}
/*
@@ -64076,6 +61022,7 @@ static SQLITE_NOINLINE int pagerOpenSavepoint(Pager *pPager, int nSavepoint){
}
aNew[ii].iSubRec = pPager->nSubRec;
aNew[ii].pInSavepoint = sqlcipher_sqlite3BitvecCreate(pPager->dbSize);
+ aNew[ii].bTruncateOnRelease = 1;
if( !aNew[ii].pInSavepoint ){
return SQLITE_NOMEM_BKPT;
}
@@ -64154,16 +61101,18 @@ SQLITE_PRIVATE int sqlcipher_sqlite3PagerSavepoint(Pager *pPager, int op, int iS
}
pPager->nSavepoint = nNew;
- /* If this is a release of the outermost savepoint, truncate
- ** the sub-journal to zero bytes in size. */
+ /* Truncate the sub-journal so that it only includes the parts
+ ** that are still in use. */
if( op==SAVEPOINT_RELEASE ){
- if( nNew==0 && isOpen(pPager->sjfd) ){
+ PagerSavepoint *pRel = &pPager->aSavepoint[nNew];
+ if( pRel->bTruncateOnRelease && isOpen(pPager->sjfd) ){
/* Only truncate if it is an in-memory sub-journal. */
if( sqlcipher_sqlite3JournalIsInMemory(pPager->sjfd) ){
- rc = sqlcipher_sqlite3OsTruncate(pPager->sjfd, 0);
+ i64 sz = (pPager->pageSize+4)*(i64)pRel->iSubRec;
+ rc = sqlcipher_sqlite3OsTruncate(pPager->sjfd, sz);
assert( rc==SQLITE_OK );
}
- pPager->nSubRec = 0;
+ pPager->nSubRec = pRel->iSubRec;
}
}
/* Else this is a rollback operation, playback the specified savepoint.
@@ -64254,7 +61203,7 @@ SQLITE_PRIVATE const char *sqlcipher_sqlite3PagerJournalname(Pager *pPager){
/*
** Set or retrieve the codec for this pager
*/
-SQLITE_PRIVATE void sqlcipher_sqlite3PagerSetCodec(
+void sqlcipherPagerSetCodec(
Pager *pPager,
void *(*xCodec)(void*,void*,Pgno,int),
void (*xCodecSizeChng)(void*,int,int),
@@ -64273,7 +61222,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3PagerSetCodec(
setGetterMethod(pPager);
pagerReportSize(pPager);
}
-SQLITE_PRIVATE void *sqlcipher_sqlite3PagerGetCodec(Pager *pPager){
+void *sqlcipherPagerGetCodec(Pager *pPager){
return pPager->pCodec;
}
@@ -64284,18 +61233,11 @@ SQLITE_PRIVATE void *sqlcipher_sqlite3PagerGetCodec(Pager *pPager){
** 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 *sqlcipher_sqlite3PagerCodec(PgHdr *pPg){
+void *sqlcipherPagerCodec(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 sqlcipher_sqlite3PagerState(Pager *pPager){
- return pPager->eState;
-}
#endif /* SQLITE_HAS_CODEC */
/* END SQLCIPHER */
@@ -64397,7 +61339,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pg
pPgOld = sqlcipher_sqlite3PagerLookup(pPager, pgno);
assert( !pPgOld || pPgOld->nRef==1 || CORRUPT_DB );
if( pPgOld ){
- if( pPgOld->nRef>1 ){
+ if( NEVER(pPgOld->nRef>1) ){
sqlcipher_sqlite3PagerUnrefNotNull(pPgOld);
return SQLITE_CORRUPT_BKPT;
}
@@ -64532,12 +61474,12 @@ SQLITE_PRIVATE int sqlcipher_sqlite3PagerSetJournalMode(Pager *pPager, int eMode
u8 eOld = pPager->journalMode; /* Prior journalmode */
/* The eMode parameter is always valid */
- assert( eMode==PAGER_JOURNALMODE_DELETE
- || eMode==PAGER_JOURNALMODE_TRUNCATE
- || eMode==PAGER_JOURNALMODE_PERSIST
- || eMode==PAGER_JOURNALMODE_OFF
- || eMode==PAGER_JOURNALMODE_WAL
- || eMode==PAGER_JOURNALMODE_MEMORY );
+ assert( eMode==PAGER_JOURNALMODE_DELETE /* 0 */
+ || eMode==PAGER_JOURNALMODE_PERSIST /* 1 */
+ || eMode==PAGER_JOURNALMODE_OFF /* 2 */
+ || eMode==PAGER_JOURNALMODE_TRUNCATE /* 3 */
+ || eMode==PAGER_JOURNALMODE_MEMORY /* 4 */
+ || eMode==PAGER_JOURNALMODE_WAL /* 5 */ );
/* This routine is only called from the OP_JournalMode opcode, and
** the logic there will never allow a temporary file to be changed
@@ -64574,7 +61516,6 @@ SQLITE_PRIVATE int sqlcipher_sqlite3PagerSetJournalMode(Pager *pPager, int eMode
assert( isOpen(pPager->fd) || pPager->exclusiveMode );
if( !pPager->exclusiveMode && (eOld & 5)==1 && (eMode & 1)==0 ){
-
/* In this case we would like to delete the journal file. If it is
** not possible, then that is not a problem. Deleting the journal file
** here is an optimization only.
@@ -64631,7 +61572,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3PagerGetJournalMode(Pager *pPager){
SQLITE_PRIVATE int sqlcipher_sqlite3PagerOkToChangeJournalMode(Pager *pPager){
assert( assert_pager_state(pPager) );
if( pPager->eState>=PAGER_WRITER_CACHEMOD ) return 0;
- if( NEVER(isOpen(pPager->jfd) && pPager->journalOff>0) ) return 0;
+ if( isOpen(pPager->jfd) && pPager->journalOff>0 ) return 0;
return 1;
}
@@ -64686,6 +61627,18 @@ SQLITE_PRIVATE int sqlcipher_sqlite3PagerCheckpoint(
int *pnCkpt /* OUT: Final number of checkpointed frames */
){
int rc = SQLITE_OK;
+ if( pPager->pWal==0 && pPager->journalMode==PAGER_JOURNALMODE_WAL ){
+ /* This only happens when a database file is zero bytes in size opened and
+ ** then "PRAGMA journal_mode=WAL" is run and then sqlcipher_sqlite3_wal_checkpoint()
+ ** is invoked without any intervening transactions. We need to start
+ ** a transaction to initialize pWal. The PRAGMA table_list statement is
+ ** used for this since it starts transactions on every database file,
+ ** including all ATTACHed databases. This seems expensive for a single
+ ** sqlcipher_sqlite3_wal_checkpoint() call, but it happens very rarely.
+ ** https://sqlite.org/forum/forumpost/fd0f19d229156939
+ */
+ sqlcipher_sqlite3_exec(db, "PRAGMA table_list",0,0,0);
+ }
if( pPager->pWal ){
rc = sqlcipher_sqlite3WalCheckpoint(pPager->pWal, db, eMode,
(eMode==SQLITE_CHECKPOINT_PASSIVE ? 0 : pPager->xBusyHandler),
@@ -64981,8 +61934,8 @@ SQLITE_PRIVATE int sqlcipher_sqlite3PagerWalFramesize(Pager *pPager){
/* BEGIN SQLCIPHER */
#ifdef SQLITE_HAS_CODEC
-SQLITE_API int sqlcipher_sqlite3pager_is_mj_pgno(Pager *pPager, Pgno pgno) {
- return (PAGER_MJ_PGNO(pPager) == pgno) ? 1 : 0;
+SQLITE_API int sqlcipher_sqlite3pager_is_sj_pgno(Pager *pPager, Pgno pgno) {
+ return (PAGER_SJ_PGNO(pPager) == pgno) ? 1 : 0;
}
SQLITE_API void sqlcipher_sqlite3pager_error(Pager *pPager, int error) {
@@ -65164,7 +62117,10 @@ SQLITE_API void sqlcipher_sqlite3pager_reset(Pager *pPager){
** HASHTABLE_NPAGE_ONE frames. The values of HASHTABLE_NPAGE_ONE and
** HASHTABLE_NPAGE are selected so that together the wal-index header and
** first index block are the same size as all other index blocks in the
-** wal-index.
+** wal-index. The values are:
+**
+** HASHTABLE_NPAGE 4096
+** HASHTABLE_NPAGE_ONE 4062
**
** Each index block contains two sections, a page-mapping that contains the
** database page number associated with each wal frame, and a hash-table
@@ -65400,6 +62356,70 @@ struct WalCkptInfo {
};
#define READMARK_NOT_USED 0xffffffff
+/*
+** This is a schematic view of the complete 136-byte header of the
+** wal-index file (also known as the -shm file):
+**
+** +-----------------------------+
+** 0: | iVersion | \
+** +-----------------------------+ |
+** 4: | (unused padding) | |
+** +-----------------------------+ |
+** 8: | iChange | |
+** +-------+-------+-------------+ |
+** 12: | bInit | bBig | szPage | |
+** +-------+-------+-------------+ |
+** 16: | mxFrame | | First copy of the
+** +-----------------------------+ | WalIndexHdr object
+** 20: | nPage | |
+** +-----------------------------+ |
+** 24: | aFrameCksum | |
+** | | |
+** +-----------------------------+ |
+** 32: | aSalt | |
+** | | |
+** +-----------------------------+ |
+** 40: | aCksum | |
+** | | /
+** +-----------------------------+
+** 48: | iVersion | \
+** +-----------------------------+ |
+** 52: | (unused padding) | |
+** +-----------------------------+ |
+** 56: | iChange | |
+** +-------+-------+-------------+ |
+** 60: | bInit | bBig | szPage | |
+** +-------+-------+-------------+ | Second copy of the
+** 64: | mxFrame | | WalIndexHdr
+** +-----------------------------+ |
+** 68: | nPage | |
+** +-----------------------------+ |
+** 72: | aFrameCksum | |
+** | | |
+** +-----------------------------+ |
+** 80: | aSalt | |
+** | | |
+** +-----------------------------+ |
+** 88: | aCksum | |
+** | | /
+** +-----------------------------+
+** 96: | nBackfill |
+** +-----------------------------+
+** 100: | 5 read marks |
+** | |
+** | |
+** | |
+** | |
+** +-------+-------+------+------+
+** 120: | Write | Ckpt | Rcvr | Rd0 | \
+** +-------+-------+------+------+ ) 8 lock bytes
+** | Read1 | Read2 | Rd3 | Rd4 | /
+** +-------+-------+------+------+
+** 128: | nBackfillAttempted |
+** +-----------------------------+
+** 132: | (unused padding) |
+** +-----------------------------+
+*/
/* A block of WALINDEX_LOCK_RESERVED bytes beginning at
** WALINDEX_LOCK_OFFSET is reserved for locks. Since some systems
@@ -65556,9 +62576,13 @@ struct WalIterator {
** so. It is safe to enlarge the wal-index if pWal->writeLock is true
** or pWal->exclusiveMode==WAL_HEAPMEMORY_MODE.
**
-** If this call is successful, *ppPage is set to point to the wal-index
-** page and SQLITE_OK is returned. If an error (an OOM or VFS error) occurs,
-** then an SQLite error code is returned and *ppPage is set to 0.
+** Three possible result scenarios:
+**
+** (1) rc==SQLITE_OK and *ppPage==Requested-Wal-Index-Page
+** (2) rc>=SQLITE_ERROR and *ppPage==NULL
+** (3) rc==SQLITE_OK and *ppPage==NULL // only if iPage==0
+**
+** Scenario (3) can only occur when pWal->writeLock is false and iPage==0
*/
static SQLITE_NOINLINE int walIndexPageRealloc(
Wal *pWal, /* The WAL context */
@@ -65591,7 +62615,9 @@ static SQLITE_NOINLINE int walIndexPageRealloc(
rc = sqlcipher_sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ,
pWal->writeLock, (void volatile **)&pWal->apWiData[iPage]
);
- assert( pWal->apWiData[iPage]!=0 || rc!=SQLITE_OK || pWal->writeLock==0 );
+ assert( pWal->apWiData[iPage]!=0
+ || rc!=SQLITE_OK
+ || (pWal->writeLock==0 && iPage==0) );
testcase( pWal->apWiData[iPage]==0 && rc==SQLITE_OK );
if( rc==SQLITE_OK ){
if( iPage>0 && sqlcipher_sqlite3FaultSim(600) ) rc = SQLITE_NOMEM;
@@ -65930,8 +62956,8 @@ struct WalHashLoc {
** slot in the hash table is set to N, it refers to frame number
** (pLoc->iZero+N) in the log.
**
-** Finally, set pLoc->aPgno so that pLoc->aPgno[1] is the page number of the
-** first frame indexed by the hash table, frame (pLoc->iZero+1).
+** Finally, set pLoc->aPgno so that pLoc->aPgno[0] is the page number of the
+** first frame indexed by the hash table, frame (pLoc->iZero).
*/
static int walHashGet(
Wal *pWal, /* WAL handle */
@@ -65943,7 +62969,7 @@ static int walHashGet(
rc = walIndexPage(pWal, iHash, &pLoc->aPgno);
assert( rc==SQLITE_OK || iHash>0 );
- if( rc==SQLITE_OK ){
+ if( pLoc->aPgno ){
pLoc->aHash = (volatile ht_slot *)&pLoc->aPgno[HASHTABLE_NPAGE];
if( iHash==0 ){
pLoc->aPgno = &pLoc->aPgno[WALINDEX_HDR_SIZE/sizeof(u32)];
@@ -65951,7 +62977,8 @@ static int walHashGet(
}else{
pLoc->iZero = HASHTABLE_NPAGE_ONE + (iHash-1)*HASHTABLE_NPAGE;
}
- pLoc->aPgno = &pLoc->aPgno[-1];
+ }else if( NEVER(rc==SQLITE_OK) ){
+ rc = SQLITE_ERROR;
}
return rc;
}
@@ -66002,7 +63029,6 @@ static void walCleanupHash(Wal *pWal){
int iLimit = 0; /* Zero values greater than this */
int nByte; /* Number of bytes to zero in aPgno[] */
int i; /* Used to iterate through aHash[] */
- int rc; /* Return code form walHashGet() */
assert( pWal->writeLock );
testcase( pWal->hdr.mxFrame==HASHTABLE_NPAGE_ONE-1 );
@@ -66017,8 +63043,8 @@ static void walCleanupHash(Wal *pWal){
*/
assert( pWal->nWiData>walFramePage(pWal->hdr.mxFrame) );
assert( pWal->apWiData[walFramePage(pWal->hdr.mxFrame)] );
- rc = walHashGet(pWal, walFramePage(pWal->hdr.mxFrame), &sLoc);
- if( NEVER(rc) ) return; /* Defense-in-depth, in case (1) above is wrong */
+ i = walHashGet(pWal, walFramePage(pWal->hdr.mxFrame), &sLoc);
+ if( NEVER(i) ) return; /* Defense-in-depth, in case (1) above is wrong */
/* Zero all hash-table entries that correspond to frame numbers greater
** than pWal->hdr.mxFrame.
@@ -66034,8 +63060,9 @@ static void walCleanupHash(Wal *pWal){
/* Zero the entries in the aPgno array that correspond to frames with
** frame numbers greater than pWal->hdr.mxFrame.
*/
- nByte = (int)((char *)sLoc.aHash - (char *)&sLoc.aPgno[iLimit+1]);
- memset((void *)&sLoc.aPgno[iLimit+1], 0, nByte);
+ nByte = (int)((char *)sLoc.aHash - (char *)&sLoc.aPgno[iLimit]);
+ assert( nByte>=0 );
+ memset((void *)&sLoc.aPgno[iLimit], 0, nByte);
#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
/* Verify that the every entry in the mapping region is still reachable
@@ -66044,11 +63071,11 @@ static void walCleanupHash(Wal *pWal){
if( iLimit ){
int j; /* Loop counter */
int iKey; /* Hash key */
- for(j=1; j<=iLimit; j++){
+ for(j=0; j<iLimit; j++){
for(iKey=walHash(sLoc.aPgno[j]);sLoc.aHash[iKey];iKey=walNextHash(iKey)){
- if( sLoc.aHash[iKey]==j ) break;
+ if( sLoc.aHash[iKey]==j+1 ) break;
}
- assert( sLoc.aHash[iKey]==j );
+ assert( sLoc.aHash[iKey]==j+1 );
}
}
#endif /* SQLITE_ENABLE_EXPENSIVE_ASSERT */
@@ -66080,9 +63107,9 @@ static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){
** entire hash table and aPgno[] array before proceeding.
*/
if( idx==1 ){
- int nByte = (int)((u8 *)&sLoc.aHash[HASHTABLE_NSLOT]
- - (u8 *)&sLoc.aPgno[1]);
- memset((void*)&sLoc.aPgno[1], 0, nByte);
+ int nByte = (int)((u8*)&sLoc.aHash[HASHTABLE_NSLOT] - (u8*)sLoc.aPgno);
+ assert( nByte>=0 );
+ memset((void*)sLoc.aPgno, 0, nByte);
}
/* If the entry in aPgno[] is already set, then the previous writer
@@ -66091,9 +63118,9 @@ static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){
** Remove the remnants of that writers uncommitted transaction from
** the hash-table before writing any new entries.
*/
- if( sLoc.aPgno[idx] ){
+ if( sLoc.aPgno[idx-1] ){
walCleanupHash(pWal);
- assert( !sLoc.aPgno[idx] );
+ assert( !sLoc.aPgno[idx-1] );
}
/* Write the aPgno[] array entry and the hash-table slot. */
@@ -66101,7 +63128,7 @@ static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){
for(iKey=walHash(iPage); sLoc.aHash[iKey]; iKey=walNextHash(iKey)){
if( (nCollide--)==0 ) return SQLITE_CORRUPT_BKPT;
}
- sLoc.aPgno[idx] = iPage;
+ sLoc.aPgno[idx-1] = iPage;
AtomicStore(&sLoc.aHash[iKey], (ht_slot)idx);
#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
@@ -66122,19 +63149,18 @@ static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){
*/
if( (idx&0x3ff)==0 ){
int i; /* Loop counter */
- for(i=1; i<=idx; i++){
+ for(i=0; i<idx; i++){
for(iKey=walHash(sLoc.aPgno[i]);
sLoc.aHash[iKey];
iKey=walNextHash(iKey)){
- if( sLoc.aHash[iKey]==i ) break;
+ if( sLoc.aHash[iKey]==i+1 ) break;
}
- assert( sLoc.aHash[iKey]==i );
+ assert( sLoc.aHash[iKey]==i+1 );
}
}
#endif /* SQLITE_ENABLE_EXPENSIVE_ASSERT */
}
-
return rc;
}
@@ -66255,7 +63281,8 @@ static int walIndexRecover(Wal *pWal){
u32 iFirst = 1 + (iPg==0?0:HASHTABLE_NPAGE_ONE+(iPg-1)*HASHTABLE_NPAGE);
u32 nHdr, nHdr32;
rc = walIndexPage(pWal, iPg, (volatile u32**)&aShare);
- if( rc ) break;
+ assert( aShare!=0 || rc!=SQLITE_OK );
+ if( aShare==0 ) break;
pWal->apWiData[iPg] = aPrivate;
for(iFrame=iFirst; iFrame<=iLast; iFrame++){
@@ -66414,14 +63441,43 @@ SQLITE_PRIVATE int sqlcipher_sqlite3WalOpen(
assert( zWalName && zWalName[0] );
assert( pDbFd );
+ /* Verify the values of various constants. Any changes to the values
+ ** of these constants would result in an incompatible on-disk format
+ ** for the -shm file. Any change that causes one of these asserts to
+ ** fail is a backward compatibility problem, even if the change otherwise
+ ** works.
+ **
+ ** This table also serves as a helpful cross-reference when trying to
+ ** interpret hex dumps of the -shm file.
+ */
+ assert( 48 == sizeof(WalIndexHdr) );
+ assert( 40 == sizeof(WalCkptInfo) );
+ assert( 120 == WALINDEX_LOCK_OFFSET );
+ assert( 136 == WALINDEX_HDR_SIZE );
+ assert( 4096 == HASHTABLE_NPAGE );
+ assert( 4062 == HASHTABLE_NPAGE_ONE );
+ assert( 8192 == HASHTABLE_NSLOT );
+ assert( 383 == HASHTABLE_HASH_1 );
+ assert( 32768 == WALINDEX_PGSZ );
+ assert( 8 == SQLITE_SHM_NLOCK );
+ assert( 5 == WAL_NREADER );
+ assert( 24 == WAL_FRAME_HDRSIZE );
+ assert( 32 == WAL_HDRSIZE );
+ assert( 120 == WALINDEX_LOCK_OFFSET + WAL_WRITE_LOCK );
+ assert( 121 == WALINDEX_LOCK_OFFSET + WAL_CKPT_LOCK );
+ assert( 122 == WALINDEX_LOCK_OFFSET + WAL_RECOVER_LOCK );
+ assert( 123 == WALINDEX_LOCK_OFFSET + WAL_READ_LOCK(0) );
+ assert( 124 == WALINDEX_LOCK_OFFSET + WAL_READ_LOCK(1) );
+ assert( 125 == WALINDEX_LOCK_OFFSET + WAL_READ_LOCK(2) );
+ assert( 126 == WALINDEX_LOCK_OFFSET + WAL_READ_LOCK(3) );
+ assert( 127 == WALINDEX_LOCK_OFFSET + WAL_READ_LOCK(4) );
+
/* In the amalgamation, the os_unix.c and os_win.c source files come before
** this source file. Verify that the #defines of the locking byte offsets
** in os_unix.c and os_win.c agree with the WALINDEX_LOCK_OFFSET value.
** For that matter, if the lock offset ever changes from its initial design
** value of 120, we need to know that so there is an assert() to check it.
*/
- assert( 120==WALINDEX_LOCK_OFFSET );
- assert( 136==WALINDEX_HDR_SIZE );
#ifdef WIN_SHM_BASE
assert( WIN_SHM_BASE==WALINDEX_LOCK_OFFSET );
#endif
@@ -66723,7 +63779,6 @@ static int walIteratorInit(Wal *pWal, u32 nBackfill, WalIterator **pp){
int nEntry; /* Number of entries in this segment */
ht_slot *aIndex; /* Sorted index for this segment */
- sLoc.aPgno++;
if( (i+1)==nSegment ){
nEntry = (int)(iLast - sLoc.iZero);
}else{
@@ -67504,7 +64559,9 @@ static int walBeginShmUnreliable(Wal *pWal, int *pChanged){
}
/* Allocate a buffer to read frames into */
- szFrame = pWal->hdr.szPage + WAL_FRAME_HDRSIZE;
+ assert( (pWal->szPage & (pWal->szPage-1))==0 );
+ assert( pWal->szPage>=512 && pWal->szPage<=65536 );
+ szFrame = pWal->szPage + WAL_FRAME_HDRSIZE;
aFrame = (u8 *)sqlcipher_sqlite3_malloc64(szFrame);
if( aFrame==0 ){
rc = SQLITE_NOMEM_BKPT;
@@ -67518,7 +64575,7 @@ static int walBeginShmUnreliable(Wal *pWal, int *pChanged){
** the caller. */
aSaveCksum[0] = pWal->hdr.aFrameCksum[0];
aSaveCksum[1] = pWal->hdr.aFrameCksum[1];
- for(iOffset=walFrameOffset(pWal->hdr.mxFrame+1, pWal->hdr.szPage);
+ for(iOffset=walFrameOffset(pWal->hdr.mxFrame+1, pWal->szPage);
iOffset+szFrame<=szWal;
iOffset+=szFrame
){
@@ -67862,7 +64919,8 @@ SQLITE_PRIVATE int sqlcipher_sqlite3WalSnapshotRecover(Wal *pWal){
rc = walHashGet(pWal, walFramePage(i), &sLoc);
if( rc!=SQLITE_OK ) break;
- pgno = sLoc.aPgno[i-sLoc.iZero];
+ assert( i - sLoc.iZero - 1 >=0 );
+ pgno = sLoc.aPgno[i-sLoc.iZero-1];
iDbOff = (i64)(pgno-1) * szPage;
if( iDbOff+szPage<=szDb ){
@@ -68095,7 +65153,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3WalFindFrame(
iKey = walHash(pgno);
while( (iH = AtomicLoad(&sLoc.aHash[iKey]))!=0 ){
u32 iFrame = iH + sLoc.iZero;
- if( iFrame<=iLast && iFrame>=pWal->minFrame && sLoc.aPgno[iH]==pgno ){
+ if( iFrame<=iLast && iFrame>=pWal->minFrame && sLoc.aPgno[iH-1]==pgno ){
assert( iFrame>iRead || CORRUPT_DB );
iRead = iFrame;
}
@@ -68434,7 +65492,7 @@ static int walWriteOneFrame(
void *pData; /* Data actually written */
u8 aFrame[WAL_FRAME_HDRSIZE]; /* Buffer to assemble frame-header in */
#if defined(SQLITE_HAS_CODEC)
- if( (pData = sqlcipher_sqlite3PagerCodec(pPage))==0 ) return SQLITE_NOMEM_BKPT;
+ if( (pData = sqlcipherPagerCodec(pPage))==0 ) return SQLITE_NOMEM_BKPT;
#else
pData = pPage->pData;
#endif
@@ -68621,7 +65679,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3WalFrames(
pWal->iReCksum = iWrite;
}
#if defined(SQLITE_HAS_CODEC)
- if( (pData = sqlcipher_sqlite3PagerCodec(p))==0 ) return SQLITE_NOMEM;
+ if( (pData = sqlcipherPagerCodec(p))==0 ) return SQLITE_NOMEM;
#else
pData = p->pData;
#endif
@@ -69079,7 +66137,742 @@ SQLITE_PRIVATE sqlcipher_sqlite3_file *sqlcipher_sqlite3WalFile(Wal *pWal){
** big and we want to break it down some. This packaged seemed like
** a good breakout.
*/
-/* #include "btreeInt.h" */
+/************** Include btreeInt.h in the middle of btmutex.c ****************/
+/************** Begin file btreeInt.h ****************************************/
+/*
+** 2004 April 6
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file implements an external (disk-based) database using BTrees.
+** For a detailed discussion of BTrees, refer to
+**
+** Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3:
+** "Sorting And Searching", pages 473-480. Addison-Wesley
+** Publishing Company, Reading, Massachusetts.
+**
+** The basic idea is that each page of the file contains N database
+** entries and N+1 pointers to subpages.
+**
+** ----------------------------------------------------------------
+** | Ptr(0) | Key(0) | Ptr(1) | Key(1) | ... | Key(N-1) | Ptr(N) |
+** ----------------------------------------------------------------
+**
+** All of the keys on the page that Ptr(0) points to have values less
+** than Key(0). All of the keys on page Ptr(1) and its subpages have
+** values greater than Key(0) and less than Key(1). All of the keys
+** on Ptr(N) and its subpages have values greater than Key(N-1). And
+** so forth.
+**
+** Finding a particular key requires reading O(log(M)) pages from the
+** disk where M is the number of entries in the tree.
+**
+** In this implementation, a single file can hold one or more separate
+** BTrees. Each BTree is identified by the index of its root page. The
+** key and data for any entry are combined to form the "payload". A
+** fixed amount of payload can be carried directly on the database
+** page. If the payload is larger than the preset amount then surplus
+** bytes are stored on overflow pages. The payload for an entry
+** and the preceding pointer are combined to form a "Cell". Each
+** page has a small header which contains the Ptr(N) pointer and other
+** information such as the size of key and data.
+**
+** FORMAT DETAILS
+**
+** The file is divided into pages. The first page is called page 1,
+** the second is page 2, and so forth. A page number of zero indicates
+** "no such page". The page size can be any power of 2 between 512 and 65536.
+** Each page can be either a btree page, a freelist page, an overflow
+** page, or a pointer-map page.
+**
+** The first page is always a btree page. The first 100 bytes of the first
+** page contain a special header (the "file header") that describes the file.
+** The format of the file header is as follows:
+**
+** OFFSET SIZE DESCRIPTION
+** 0 16 Header string: "SQLite format 3\000"
+** 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 (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
+** 36 4 Number of freelist pages in the file
+** 40 60 15 4-byte meta values passed to higher layers
+**
+** 40 4 Schema cookie
+** 44 4 File format of schema layer
+** 48 4 Size of page cache
+** 52 4 Largest root-page (auto/incr_vacuum)
+** 56 4 1=UTF-8 2=UTF16le 3=UTF16be
+** 60 4 User version
+** 64 4 Incremental vacuum mode
+** 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).
+**
+** The file change counter is incremented when the database is changed
+** This counter allows other processes to know when the file has changed
+** and thus when they need to flush their cache.
+**
+** The max embedded payload fraction is the amount of the total usable
+** space in a page that can be consumed by a single cell for standard
+** B-tree (non-LEAFDATA) tables. A value of 255 means 100%. The default
+** is to limit the maximum cell size so that at least 4 cells will fit
+** on one page. Thus the default max embedded payload fraction is 64.
+**
+** If the payload for a cell is larger than the max payload, then extra
+** payload is spilled to overflow pages. Once an overflow page is allocated,
+** as many bytes as possible are moved into the overflow pages without letting
+** the cell size drop below the min embedded payload fraction.
+**
+** The min leaf payload fraction is like the min embedded payload fraction
+** except that it applies to leaf nodes in a LEAFDATA tree. The maximum
+** payload fraction for a LEAFDATA tree is always 100% (or 255) and it
+** not specified in the header.
+**
+** Each btree pages is divided into three sections: The header, the
+** cell pointer array, and the cell content area. Page 1 also has a 100-byte
+** file header that occurs before the page header.
+**
+** |----------------|
+** | file header | 100 bytes. Page 1 only.
+** |----------------|
+** | page header | 8 bytes for leaves. 12 bytes for interior nodes
+** |----------------|
+** | cell pointer | | 2 bytes per cell. Sorted order.
+** | array | | Grows downward
+** | | v
+** |----------------|
+** | unallocated |
+** | space |
+** |----------------| ^ Grows upwards
+** | cell content | | Arbitrary order interspersed with freeblocks.
+** | area | | and free space fragments.
+** |----------------|
+**
+** The page headers looks like this:
+**
+** OFFSET SIZE DESCRIPTION
+** 0 1 Flags. 1: intkey, 2: zerodata, 4: leafdata, 8: leaf
+** 1 2 byte offset to the first freeblock
+** 3 2 number of cells on this page
+** 5 2 first byte of the cell content area
+** 7 1 number of fragmented free bytes
+** 8 4 Right child (the Ptr(N) value). Omitted on leaves.
+**
+** The flags define the format of this btree page. The leaf flag means that
+** this page has no children. The zerodata flag means that this page carries
+** only keys and no data. The intkey flag means that the key is an integer
+** which is stored in the key size entry of the cell header rather than in
+** the payload area.
+**
+** The cell pointer array begins on the first byte after the page header.
+** The cell pointer array contains zero or more 2-byte numbers which are
+** offsets from the beginning of the page to the cell content in the cell
+** content area. The cell pointers occur in sorted order. The system strives
+** to keep free space after the last cell pointer so that new cells can
+** be easily added without having to defragment the page.
+**
+** Cell content is stored at the very end of the page and grows toward the
+** beginning of the page.
+**
+** Unused space within the cell content area is collected into a linked list of
+** freeblocks. Each freeblock is at least 4 bytes in size. The byte offset
+** to the first freeblock is given in the header. Freeblocks occur in
+** increasing order. Because a freeblock must be at least 4 bytes in size,
+** any group of 3 or fewer unused bytes in the cell content area cannot
+** exist on the freeblock chain. A group of 3 or fewer free bytes is called
+** a fragment. The total number of bytes in all fragments is recorded.
+** in the page header at offset 7.
+**
+** SIZE DESCRIPTION
+** 2 Byte offset of the next freeblock
+** 2 Bytes in this freeblock
+**
+** Cells are of variable length. Cells are stored in the cell content area at
+** the end of the page. Pointers to the cells are in the cell pointer array
+** that immediately follows the page header. Cells is not necessarily
+** contiguous or in order, but cell pointers are contiguous and in order.
+**
+** Cell content makes use of variable length integers. A variable
+** length integer is 1 to 9 bytes where the lower 7 bits of each
+** byte are used. The integer consists of all bytes that have bit 8 set and
+** the first byte with bit 8 clear. The most significant byte of the integer
+** appears first. A variable-length integer may not be more than 9 bytes long.
+** As a special case, all 8 bytes of the 9th byte are used as data. This
+** allows a 64-bit integer to be encoded in 9 bytes.
+**
+** 0x00 becomes 0x00000000
+** 0x7f becomes 0x0000007f
+** 0x81 0x00 becomes 0x00000080
+** 0x82 0x00 becomes 0x00000100
+** 0x80 0x7f becomes 0x0000007f
+** 0x8a 0x91 0xd1 0xac 0x78 becomes 0x12345678
+** 0x81 0x81 0x81 0x81 0x01 becomes 0x10204081
+**
+** Variable length integers are used for rowids and to hold the number of
+** bytes of key and data in a btree cell.
+**
+** The content of a cell looks like this:
+**
+** SIZE DESCRIPTION
+** 4 Page number of the left child. Omitted if leaf flag is set.
+** var Number of bytes of data. Omitted if the zerodata flag is set.
+** var Number of bytes of key. Or the key itself if intkey flag is set.
+** * Payload
+** 4 First page of the overflow chain. Omitted if no overflow
+**
+** Overflow pages form a linked list. Each page except the last is completely
+** filled with data (pagesize - 4 bytes). The last page can have as little
+** as 1 byte of data.
+**
+** SIZE DESCRIPTION
+** 4 Page number of next overflow page
+** * Data
+**
+** Freelist pages come in two subtypes: trunk pages and leaf pages. The
+** file header points to the first in a linked list of trunk page. Each trunk
+** page points to multiple leaf pages. The content of a leaf page is
+** unspecified. A trunk page looks like this:
+**
+** SIZE DESCRIPTION
+** 4 Page number of next trunk page
+** 4 Number of leaf pointers on this page
+** * zero or more pages numbers of leaves
+*/
+/* #include "sqliteInt.h" */
+
+
+/* The following value is the maximum cell size assuming a maximum page
+** size give above.
+*/
+#define MX_CELL_SIZE(pBt) ((int)(pBt->pageSize-8))
+
+/* The maximum number of cells on a single page of the database. This
+** assumes a minimum cell size of 6 bytes (4 bytes for the cell itself
+** plus 2 bytes for the index to the cell in the page header). Such
+** small cells will be rare, but they are possible.
+*/
+#define MX_CELL(pBt) ((pBt->pageSize-8)/6)
+
+/* Forward declarations */
+typedef struct MemPage MemPage;
+typedef struct BtLock BtLock;
+typedef struct CellInfo CellInfo;
+
+/*
+** This is a magic string that appears at the beginning of every
+** SQLite database in order to identify the file as a real database.
+**
+** You can change this value at compile-time by specifying a
+** -DSQLITE_FILE_HEADER="..." on the compiler command-line. The
+** header must be exactly 16 bytes including the zero-terminator so
+** the string itself should be 15 characters long. If you change
+** the header, then your custom library will not be able to read
+** databases generated by the standard tools and the standard tools
+** will not be able to read databases created by your custom library.
+*/
+#ifndef SQLITE_FILE_HEADER /* 123456789 123456 */
+# define SQLITE_FILE_HEADER "SQLite format 3"
+#endif
+
+/*
+** Page type flags. An ORed combination of these flags appear as the
+** first byte of on-disk image of every BTree page.
+*/
+#define PTF_INTKEY 0x01
+#define PTF_ZERODATA 0x02
+#define PTF_LEAFDATA 0x04
+#define PTF_LEAF 0x08
+
+/*
+** An instance of this object stores information about each a single database
+** page that has been loaded into memory. The information in this object
+** is derived from the raw on-disk page content.
+**
+** As each database page is loaded into memory, the pager allocats an
+** instance of this object and zeros the first 8 bytes. (This is the
+** "extra" information associated with each page of the pager.)
+**
+** Access to all fields of this structure is controlled by the mutex
+** stored in MemPage.pBt->mutex.
+*/
+struct MemPage {
+ u8 isInit; /* True if previously initialized. MUST BE FIRST! */
+ u8 intKey; /* True if table b-trees. False for index b-trees */
+ u8 intKeyLeaf; /* True if the leaf of an intKey table */
+ Pgno pgno; /* Page number for this page */
+ /* Only the first 8 bytes (above) are zeroed by pager.c when a new page
+ ** is allocated. All fields that follow must be initialized before use */
+ u8 leaf; /* True if a leaf page */
+ u8 hdrOffset; /* 100 for page 1. 0 otherwise */
+ u8 childPtrSize; /* 0 if leaf==1. 4 if leaf==0 */
+ u8 max1bytePayload; /* min(maxLocal,127) */
+ u8 nOverflow; /* Number of overflow cell bodies in aCell[] */
+ u16 maxLocal; /* Copy of BtShared.maxLocal or BtShared.maxLeaf */
+ u16 minLocal; /* Copy of BtShared.minLocal or BtShared.minLeaf */
+ u16 cellOffset; /* Index in aData of first cell pointer */
+ int nFree; /* Number of free bytes on the page. -1 for unknown */
+ u16 nCell; /* Number of cells on this page, local and ovfl */
+ u16 maskPage; /* Mask for page offset */
+ u16 aiOvfl[4]; /* Insert the i-th overflow cell before the aiOvfl-th
+ ** non-overflow cell */
+ u8 *apOvfl[4]; /* Pointers to the body of overflow cells */
+ BtShared *pBt; /* Pointer to BtShared that this page is part of */
+ u8 *aData; /* Pointer to disk image of the page data */
+ u8 *aDataEnd; /* One byte past the end of the entire page - not just
+ ** the usable space, the entire page. Used to prevent
+ ** corruption-induced buffer overflow. */
+ u8 *aCellIdx; /* The cell index area */
+ u8 *aDataOfst; /* Same as aData for leaves. aData+4 for interior */
+ DbPage *pDbPage; /* Pager page handle */
+ u16 (*xCellSize)(MemPage*,u8*); /* cellSizePtr method */
+ void (*xParseCell)(MemPage*,u8*,CellInfo*); /* btreeParseCell method */
+};
+
+/*
+** A linked list of the following structures is stored at BtShared.pLock.
+** Locks are added (or upgraded from READ_LOCK to WRITE_LOCK) when a cursor
+** is opened on the table with root page BtShared.iTable. Locks are removed
+** from this list when a transaction is committed or rolled back, or when
+** a btree handle is closed.
+*/
+struct BtLock {
+ Btree *pBtree; /* Btree handle holding this lock */
+ Pgno iTable; /* Root page of table */
+ u8 eLock; /* READ_LOCK or WRITE_LOCK */
+ BtLock *pNext; /* Next in BtShared.pLock list */
+};
+
+/* Candidate values for BtLock.eLock */
+#define READ_LOCK 1
+#define WRITE_LOCK 2
+
+/* A Btree handle
+**
+** A database connection contains a pointer to an instance of
+** this object for every database file that it has open. This structure
+** is opaque to the database connection. The database connection cannot
+** see the internals of this structure and only deals with pointers to
+** this structure.
+**
+** For some database files, the same underlying database cache might be
+** shared between multiple connections. In that case, each connection
+** has it own instance of this object. But each instance of this object
+** points to the same BtShared object. The database cache and the
+** schema associated with the database file are all contained within
+** the BtShared object.
+**
+** All fields in this structure are accessed under sqlcipher_sqlite3.mutex.
+** The pBt pointer itself may not be changed while there exists cursors
+** in the referenced BtShared that point back to this Btree since those
+** cursors have to go through this Btree to find their BtShared and
+** they often do so without holding sqlcipher_sqlite3.mutex.
+*/
+struct Btree {
+ sqlcipher_sqlite3 *db; /* The database connection holding this btree */
+ BtShared *pBt; /* Sharable content of this btree */
+ u8 inTrans; /* TRANS_NONE, TRANS_READ or TRANS_WRITE */
+ u8 sharable; /* True if we can share pBt with another db */
+ u8 locked; /* True if db currently has pBt locked */
+ u8 hasIncrblobCur; /* True if there are one or more Incrblob cursors */
+ int wantToLock; /* Number of nested calls to sqlcipher_sqlite3BtreeEnter() */
+ int nBackup; /* Number of backup operations reading this btree */
+ u32 iBDataVersion; /* Combines with pBt->pPager->iDataVersion */
+ Btree *pNext; /* List of other sharable Btrees from the same db */
+ Btree *pPrev; /* Back pointer of the same list */
+#ifdef SQLITE_DEBUG
+ u64 nSeek; /* Calls to sqlcipher_sqlite3BtreeMovetoUnpacked() */
+#endif
+#ifndef SQLITE_OMIT_SHARED_CACHE
+ BtLock lock; /* Object used to lock page 1 */
+#endif
+};
+
+/*
+** Btree.inTrans may take one of the following values.
+**
+** If the shared-data extension is enabled, there may be multiple users
+** of the Btree structure. At most one of these may open a write transaction,
+** but any number may have active read transactions.
+**
+** These values must match SQLITE_TXN_NONE, SQLITE_TXN_READ, and
+** SQLITE_TXN_WRITE
+*/
+#define TRANS_NONE 0
+#define TRANS_READ 1
+#define TRANS_WRITE 2
+
+#if TRANS_NONE!=SQLITE_TXN_NONE
+# error wrong numeric code for no-transaction
+#endif
+#if TRANS_READ!=SQLITE_TXN_READ
+# error wrong numeric code for read-transaction
+#endif
+#if TRANS_WRITE!=SQLITE_TXN_WRITE
+# error wrong numeric code for write-transaction
+#endif
+
+
+/*
+** An instance of this object represents a single database file.
+**
+** A single database file can be in use at the same time by two
+** or more database connections. When two or more connections are
+** sharing the same database file, each connection has it own
+** private Btree object for the file and each of those Btrees points
+** to this one BtShared object. BtShared.nRef is the number of
+** connections currently sharing this database file.
+**
+** Fields in this structure are accessed under the BtShared.mutex
+** mutex, except for nRef and pNext which are accessed under the
+** global SQLITE_MUTEX_STATIC_MAIN mutex. The pPager field
+** may not be modified once it is initially set as long as nRef>0.
+** The pSchema field may be set once under BtShared.mutex and
+** thereafter is unchanged as long as nRef>0.
+**
+** isPending:
+**
+** If a BtShared client fails to obtain a write-lock on a database
+** table (because there exists one or more read-locks on the table),
+** the shared-cache enters 'pending-lock' state and isPending is
+** set to true.
+**
+** The shared-cache leaves the 'pending lock' state when either of
+** the following occur:
+**
+** 1) The current writer (BtShared.pWriter) concludes its transaction, OR
+** 2) The number of locks held by other connections drops to zero.
+**
+** while in the 'pending-lock' state, no connection may start a new
+** transaction.
+**
+** This feature is included to help prevent writer-starvation.
+*/
+struct BtShared {
+ Pager *pPager; /* The page cache */
+ sqlcipher_sqlite3 *db; /* Database connection currently using this Btree */
+ BtCursor *pCursor; /* A list of all open cursors */
+ MemPage *pPage1; /* First page of the database */
+ u8 openFlags; /* Flags to sqlcipher_sqlite3BtreeOpen() */
+#ifndef SQLITE_OMIT_AUTOVACUUM
+ u8 autoVacuum; /* True if auto-vacuum is enabled */
+ u8 incrVacuum; /* True if incr-vacuum is enabled */
+ u8 bDoTruncate; /* True to truncate db on commit */
+#endif
+ u8 inTransaction; /* Transaction state */
+ u8 max1bytePayload; /* Maximum first byte of cell for a 1-byte payload */
+ u8 nReserveWanted; /* Desired number of extra bytes per page */
+ u16 btsFlags; /* Boolean parameters. See BTS_* macros below */
+ u16 maxLocal; /* Maximum local payload in non-LEAFDATA tables */
+ u16 minLocal; /* Minimum local payload in non-LEAFDATA tables */
+ u16 maxLeaf; /* Maximum local payload in a LEAFDATA table */
+ u16 minLeaf; /* Minimum local payload in a LEAFDATA table */
+ u32 pageSize; /* Total number of bytes on a page */
+ u32 usableSize; /* Number of usable bytes on each page */
+ int nTransaction; /* Number of open transactions (read + write) */
+ u32 nPage; /* Number of pages in the database */
+ void *pSchema; /* Pointer to space allocated by sqlcipher_sqlite3BtreeSchema() */
+ void (*xFreeSchema)(void*); /* Destructor for BtShared.pSchema */
+ sqlcipher_sqlite3_mutex *mutex; /* Non-recursive mutex required to access this object */
+ Bitvec *pHasContent; /* Set of pages moved to free-list this transaction */
+#ifndef SQLITE_OMIT_SHARED_CACHE
+ int nRef; /* Number of references to this structure */
+ BtShared *pNext; /* Next on a list of sharable BtShared structs */
+ BtLock *pLock; /* List of locks held on this shared-btree struct */
+ Btree *pWriter; /* Btree with currently open write transaction */
+#endif
+ u8 *pTmpSpace; /* Temp space sufficient to hold a single cell */
+ int nPreformatSize; /* Size of last cell written by TransferRow() */
+};
+
+/*
+** Allowed values for BtShared.btsFlags
+*/
+#define BTS_READ_ONLY 0x0001 /* Underlying file is readonly */
+#define BTS_PAGESIZE_FIXED 0x0002 /* Page size can no longer be changed */
+#define BTS_SECURE_DELETE 0x0004 /* PRAGMA secure_delete is enabled */
+#define BTS_OVERWRITE 0x0008 /* Overwrite deleted content with zeros */
+#define BTS_FAST_SECURE 0x000c /* Combination of the previous two */
+#define BTS_INITIALLY_EMPTY 0x0010 /* Database was empty at trans start */
+#define BTS_NO_WAL 0x0020 /* Do not open write-ahead-log files */
+#define BTS_EXCLUSIVE 0x0040 /* pWriter has an exclusive lock */
+#define BTS_PENDING 0x0080 /* Waiting for read-locks to clear */
+
+/*
+** An instance of the following structure is used to hold information
+** about a cell. The parseCellPtr() function fills in this structure
+** based on information extract from the raw disk page.
+*/
+struct CellInfo {
+ i64 nKey; /* The key for INTKEY tables, or nPayload otherwise */
+ u8 *pPayload; /* Pointer to the start of payload */
+ u32 nPayload; /* Bytes of payload */
+ u16 nLocal; /* Amount of payload held locally, not on overflow */
+ u16 nSize; /* Size of the cell content on the main b-tree page */
+};
+
+/*
+** Maximum depth of an SQLite B-Tree structure. Any B-Tree deeper than
+** this will be declared corrupt. This value is calculated based on a
+** maximum database size of 2^31 pages a minimum fanout of 2 for a
+** root-node and 3 for all other internal nodes.
+**
+** If a tree that appears to be taller than this is encountered, it is
+** assumed that the database is corrupt.
+*/
+#define BTCURSOR_MAX_DEPTH 20
+
+/*
+** A cursor is a pointer to a particular entry within a particular
+** b-tree within a database file.
+**
+** The entry is identified by its MemPage and the index in
+** MemPage.aCell[] of the entry.
+**
+** A single database file can be shared by two more database connections,
+** but cursors cannot be shared. Each cursor is associated with a
+** particular database connection identified BtCursor.pBtree.db.
+**
+** Fields in this structure are accessed under the BtShared.mutex
+** found at self->pBt->mutex.
+**
+** skipNext meaning:
+** The meaning of skipNext depends on the value of eState:
+**
+** eState Meaning of skipNext
+** VALID skipNext is meaningless and is ignored
+** INVALID skipNext is meaningless and is ignored
+** SKIPNEXT sqlcipher_sqlite3BtreeNext() is a no-op if skipNext>0 and
+** sqlcipher_sqlite3BtreePrevious() is no-op if skipNext<0.
+** REQUIRESEEK restoreCursorPosition() restores the cursor to
+** eState=SKIPNEXT if skipNext!=0
+** FAULT skipNext holds the cursor fault error code.
+*/
+struct BtCursor {
+ u8 eState; /* One of the CURSOR_XXX constants (see below) */
+ u8 curFlags; /* zero or more BTCF_* flags defined below */
+ u8 curPagerFlags; /* Flags to send to sqlcipher_sqlite3PagerGet() */
+ u8 hints; /* As configured by CursorSetHints() */
+ int skipNext; /* Prev() is noop if negative. Next() is noop if positive.
+ ** Error code if eState==CURSOR_FAULT */
+ Btree *pBtree; /* The Btree to which this cursor belongs */
+ Pgno *aOverflow; /* Cache of overflow page locations */
+ void *pKey; /* Saved key that was cursor last known position */
+ /* All fields above are zeroed when the cursor is allocated. See
+ ** sqlcipher_sqlite3BtreeCursorZero(). Fields that follow must be manually
+ ** initialized. */
+#define BTCURSOR_FIRST_UNINIT pBt /* Name of first uninitialized field */
+ BtShared *pBt; /* The BtShared this cursor points to */
+ BtCursor *pNext; /* Forms a linked list of all cursors */
+ CellInfo info; /* A parse of the cell we are pointing at */
+ i64 nKey; /* Size of pKey, or last integer key */
+ Pgno pgnoRoot; /* The root page of this tree */
+ i8 iPage; /* Index of current page in apPage */
+ u8 curIntKey; /* Value of apPage[0]->intKey */
+ u16 ix; /* Current index for apPage[iPage] */
+ u16 aiIdx[BTCURSOR_MAX_DEPTH-1]; /* Current index in apPage[i] */
+ struct KeyInfo *pKeyInfo; /* Arg passed to comparison function */
+ MemPage *pPage; /* Current page */
+ MemPage *apPage[BTCURSOR_MAX_DEPTH-1]; /* Stack of parents of current page */
+};
+
+/*
+** 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 */
+#define BTCF_Multiple 0x20 /* Maybe another cursor on the same btree */
+#define BTCF_Pinned 0x40 /* Cursor is busy and cannot be moved */
+
+/*
+** Potential values for BtCursor.eState.
+**
+** 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 sqlcipher_sqlite3BtreeNext() or sqlcipher_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
+** in variables BtCursor.pKey and BtCursor.nKey. When a cursor is in
+** this state, restoreCursorPosition() can be called to attempt to
+** seek the cursor to the saved position.
+**
+** CURSOR_FAULT:
+** An unrecoverable error (an I/O error or a malloc failure) has occurred
+** on a different connection that shares the BtShared cache with this
+** cursor. The error has left the cache in an inconsistent state.
+** Do nothing else with this cursor. Any attempt to use the cursor
+** should return the error code stored in BtCursor.skipNext
+*/
+#define CURSOR_VALID 0
+#define CURSOR_INVALID 1
+#define CURSOR_SKIPNEXT 2
+#define CURSOR_REQUIRESEEK 3
+#define CURSOR_FAULT 4
+
+/*
+** The database page the PENDING_BYTE occupies. This page is never used.
+*/
+#define PENDING_BYTE_PAGE(pBt) ((Pgno)((PENDING_BYTE/((pBt)->pageSize))+1))
+
+/*
+** These macros define the location of the pointer-map entry for a
+** database page. The first argument to each is the number of usable
+** bytes on each page of the database (often 1024). The second is the
+** page number to look up in the pointer map.
+**
+** PTRMAP_PAGENO returns the database page number of the pointer-map
+** page that stores the required pointer. PTRMAP_PTROFFSET returns
+** the offset of the requested map entry.
+**
+** If the pgno argument passed to PTRMAP_PAGENO is a pointer-map page,
+** then pgno is returned. So (pgno==PTRMAP_PAGENO(pgsz, pgno)) can be
+** used to test if pgno is a pointer-map page. PTRMAP_ISPAGE implements
+** this test.
+*/
+#define PTRMAP_PAGENO(pBt, pgno) ptrmapPageno(pBt, pgno)
+#define PTRMAP_PTROFFSET(pgptrmap, pgno) (5*(pgno-pgptrmap-1))
+#define PTRMAP_ISPAGE(pBt, pgno) (PTRMAP_PAGENO((pBt),(pgno))==(pgno))
+
+/*
+** The pointer map is a lookup table that identifies the parent page for
+** each child page in the database file. The parent page is the page that
+** contains a pointer to the child. Every page in the database contains
+** 0 or 1 parent pages. (In this context 'database page' refers
+** to any page that is not part of the pointer map itself.) Each pointer map
+** entry consists of a single byte 'type' and a 4 byte parent page number.
+** The PTRMAP_XXX identifiers below are the valid types.
+**
+** The purpose of the pointer map is to facility moving pages from one
+** position in the file to another as part of autovacuum. When a page
+** is moved, the pointer in its parent must be updated to point to the
+** new location. The pointer map is used to locate the parent page quickly.
+**
+** PTRMAP_ROOTPAGE: The database page is a root-page. The page-number is not
+** used in this case.
+**
+** PTRMAP_FREEPAGE: The database page is an unused (free) page. The page-number
+** is not used in this case.
+**
+** PTRMAP_OVERFLOW1: The database page is the first page in a list of
+** overflow pages. The page number identifies the page that
+** contains the cell with a pointer to this overflow page.
+**
+** PTRMAP_OVERFLOW2: The database page is the second or later page in a list of
+** overflow pages. The page-number identifies the previous
+** page in the overflow page list.
+**
+** PTRMAP_BTREE: The database page is a non-root btree page. The page number
+** identifies the parent page in the btree.
+*/
+#define PTRMAP_ROOTPAGE 1
+#define PTRMAP_FREEPAGE 2
+#define PTRMAP_OVERFLOW1 3
+#define PTRMAP_OVERFLOW2 4
+#define PTRMAP_BTREE 5
+
+/* A bunch of assert() statements to check the transaction state variables
+** of handle p (type Btree*) are internally consistent.
+*/
+#define btreeIntegrity(p) \
+ assert( p->pBt->inTransaction!=TRANS_NONE || p->pBt->nTransaction==0 ); \
+ assert( p->pBt->inTransaction>=p->inTrans );
+
+
+/*
+** The ISAUTOVACUUM macro is used within balance_nonroot() to determine
+** if the database supports auto-vacuum or not. Because it is used
+** within an expression that is an argument to another macro
+** (sqliteMallocRaw), it is not possible to use conditional compilation.
+** So, this macro is defined instead.
+*/
+#ifndef SQLITE_OMIT_AUTOVACUUM
+#define ISAUTOVACUUM (pBt->autoVacuum)
+#else
+#define ISAUTOVACUUM 0
+#endif
+
+
+/*
+** This structure is passed around through all the sanity checking routines
+** in order to keep track of some global state information.
+**
+** The aRef[] array is allocated so that there is 1 bit for each page in
+** the database. As the integrity-check proceeds, for each page used in
+** the database the corresponding bit is set. This allows integrity-check to
+** detect pages that are used twice and orphaned pages (both of which
+** indicate corruption).
+*/
+typedef struct IntegrityCk IntegrityCk;
+struct IntegrityCk {
+ BtShared *pBt; /* The tree being checked out */
+ Pager *pPager; /* The associated pager. Also accessible by pBt->pPager */
+ u8 *aPgRef; /* 1 bit per page in the db (see above) */
+ Pgno nPage; /* Number of pages in the database */
+ int mxErr; /* Stop accumulating errors when this reaches zero */
+ int nErr; /* Number of messages written to zErrMsg so far */
+ int bOomFault; /* A memory allocation error has occurred */
+ const char *zPfx; /* Error message prefix */
+ Pgno v1; /* Value for first %u substitution in zPfx */
+ int v2; /* Value for second %d substitution in zPfx */
+ StrAccum errMsg; /* Accumulate the error message text here */
+ u32 *heap; /* Min-heap used for analyzing cell coverage */
+ sqlcipher_sqlite3 *db; /* Database connection running the check */
+};
+
+/*
+** Routines to read or write a two- and four-byte big-endian integer values.
+*/
+#define get2byte(x) ((x)[0]<<8 | (x)[1])
+#define put2byte(p,v) ((p)[0] = (u8)((v)>>8), (p)[1] = (u8)(v))
+#define get4byte sqlcipher_sqlite3Get4byte
+#define put4byte sqlcipher_sqlite3Put4byte
+
+/*
+** get2byteAligned(), unlike get2byte(), requires that its argument point to a
+** two-byte aligned address. get2bytea() is only used for accessing the
+** cell addresses in a btree header.
+*/
+#if SQLITE_BYTEORDER==4321
+# define get2byteAligned(x) (*(u16*)(x))
+#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4008000
+# define get2byteAligned(x) __builtin_bswap16(*(u16*)(x))
+#elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
+# define get2byteAligned(x) _byteswap_ushort(*(u16*)(x))
+#else
+# define get2byteAligned(x) ((x)[0]<<8 | (x)[1])
+#endif
+
+/************** End of btreeInt.h ********************************************/
+/************** Continuing where we left off in btmutex.c ********************/
#ifndef SQLITE_OMIT_SHARED_CACHE
#if SQLITE_THREADSAFE
@@ -69589,7 +67382,7 @@ static int hasSharedCacheTableLock(
int bSeen = 0;
for(p=sqliteHashFirst(&pSchema->idxHash); p; p=sqliteHashNext(p)){
Index *pIdx = (Index *)sqliteHashData(p);
- if( pIdx->tnum==(int)iRoot ){
+ if( pIdx->tnum==iRoot ){
if( bSeen ){
/* Two or more indexes share the same root page. There must
** be imposter tables. So just return true. The assert is not
@@ -69922,7 +67715,7 @@ static void invalidateIncrblobCursors(
int isClearTable /* True if all rows are being deleted */
){
BtCursor *p;
- if( pBtree->hasIncrblobCur==0 ) return;
+ assert( pBtree->hasIncrblobCur );
assert( sqlcipher_sqlite3BtreeHoldsMutex(pBtree) );
pBtree->hasIncrblobCur = 0;
for(p=pBtree->pBt->pCursor; p; p=p->pNext){
@@ -70182,7 +67975,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3BtreeClearCursor(BtCursor *pCur){
/*
** In this version of BtreeMoveto, pKey is a packed index record
** such as is generated by the OP_MakeRecord opcode. Unpack the
-** record and then call BtreeMovetoUnpacked() to do the work.
+** record and then call sqlcipher_sqlite3BtreeIndexMoveto() to do the work.
*/
static int btreeMoveto(
BtCursor *pCur, /* Cursor open on the btree to be searched */
@@ -70202,15 +67995,13 @@ static int btreeMoveto(
sqlcipher_sqlite3VdbeRecordUnpack(pKeyInfo, (int)nKey, pKey, pIdxKey);
if( pIdxKey->nField==0 || pIdxKey->nField>pKeyInfo->nAllField ){
rc = SQLITE_CORRUPT_BKPT;
- goto moveto_done;
+ }else{
+ rc = sqlcipher_sqlite3BtreeIndexMoveto(pCur, pIdxKey, pRes);
}
+ sqlcipher_sqlite3DbFree(pCur->pKeyInfo->db, pIdxKey);
}else{
pIdxKey = 0;
- }
- rc = sqlcipher_sqlite3BtreeMovetoUnpacked(pCur, pIdxKey, nKey, bias, pRes);
-moveto_done:
- if( pIdxKey ){
- sqlcipher_sqlite3DbFree(pCur->pKeyInfo->db, pIdxKey);
+ rc = sqlcipher_sqlite3BtreeTableMoveto(pCur, nKey, bias, pRes);
}
return rc;
}
@@ -70519,6 +68310,24 @@ static SQLITE_NOINLINE void btreeParseCellAdjustSizeForOverflow(
}
/*
+** Given a record with nPayload bytes of payload stored within btree
+** page pPage, return the number of bytes of payload stored locally.
+*/
+static int btreePayloadToLocal(MemPage *pPage, i64 nPayload){
+ int maxLocal; /* Maximum amount of payload held locally */
+ maxLocal = pPage->maxLocal;
+ if( nPayload<=maxLocal ){
+ return nPayload;
+ }else{
+ int minLocal; /* Minimum amount of payload held locally */
+ int surplus; /* Overflow payload available for local storage */
+ minLocal = pPage->minLocal;
+ surplus = minLocal + (nPayload - minLocal)%(pPage->pBt->usableSize-4);
+ return ( surplus <= maxLocal ) ? surplus : minLocal;
+ }
+}
+
+/*
** The following routines are implementations of the MemPage.xParseCell()
** method.
**
@@ -70584,18 +68393,32 @@ static void btreeParseCellPtr(
**
** pIter += getVarint(pIter, (u64*)&pInfo->nKey);
**
- ** The code is inlined to avoid a function call.
+ ** The code is inlined and the loop is unrolled for performance.
+ ** This routine is a high-runner.
*/
iKey = *pIter;
if( iKey>=0x80 ){
- u8 *pEnd = &pIter[7];
- iKey &= 0x7f;
- while(1){
- iKey = (iKey<<7) | (*++pIter & 0x7f);
- if( (*pIter)<0x80 ) break;
- if( pIter>=pEnd ){
- iKey = (iKey<<8) | *++pIter;
- break;
+ u8 x;
+ iKey = ((iKey&0x7f)<<7) | ((x = *++pIter) & 0x7f);
+ if( x>=0x80 ){
+ iKey = (iKey<<7) | ((x =*++pIter) & 0x7f);
+ if( x>=0x80 ){
+ iKey = (iKey<<7) | ((x = *++pIter) & 0x7f);
+ if( x>=0x80 ){
+ iKey = (iKey<<7) | ((x = *++pIter) & 0x7f);
+ if( x>=0x80 ){
+ iKey = (iKey<<7) | ((x = *++pIter) & 0x7f);
+ if( x>=0x80 ){
+ iKey = (iKey<<7) | ((x = *++pIter) & 0x7f);
+ if( x>=0x80 ){
+ iKey = (iKey<<7) | ((x = *++pIter) & 0x7f);
+ if( x>=0x80 ){
+ iKey = (iKey<<8) | (*++pIter);
+ }
+ }
+ }
+ }
+ }
}
}
}
@@ -70605,7 +68428,7 @@ static void btreeParseCellPtr(
pInfo->nPayload = nPayload;
pInfo->pPayload = pIter;
testcase( nPayload==pPage->maxLocal );
- testcase( nPayload==pPage->maxLocal+1 );
+ testcase( nPayload==(u32)pPage->maxLocal+1 );
if( nPayload<=pPage->maxLocal ){
/* This is the (easy) common case where the entire payload fits
** on the local page. No overflow is required.
@@ -70642,7 +68465,7 @@ static void btreeParseCellPtrIndex(
pInfo->nPayload = nPayload;
pInfo->pPayload = pIter;
testcase( nPayload==pPage->maxLocal );
- testcase( nPayload==pPage->maxLocal+1 );
+ testcase( nPayload==(u32)pPage->maxLocal+1 );
if( nPayload<=pPage->maxLocal ){
/* This is the (easy) common case where the entire payload fits
** on the local page. No overflow is required.
@@ -70672,6 +68495,7 @@ static void btreeParseCell(
** the space used by the cell pointer.
**
** cellSizePtrNoPayload() => table internal nodes
+** cellSizePtrTableLeaf() => table leaf nodes
** cellSizePtr() => all index nodes & table leaf nodes
*/
static u16 cellSizePtr(MemPage *pPage, u8 *pCell){
@@ -70697,15 +68521,8 @@ static u16 cellSizePtr(MemPage *pPage, u8 *pCell){
}while( *(pIter)>=0x80 && pIter<pEnd );
}
pIter++;
- if( pPage->intKey ){
- /* pIter now points at the 64-bit integer key value, a variable length
- ** integer. The following block moves pIter to point at the first byte
- ** past the end of the key value. */
- pEnd = &pIter[9];
- while( (*pIter++)&0x80 && pIter<pEnd );
- }
testcase( nSize==pPage->maxLocal );
- testcase( nSize==pPage->maxLocal+1 );
+ testcase( nSize==(u32)pPage->maxLocal+1 );
if( nSize<=pPage->maxLocal ){
nSize += (u32)(pIter - pCell);
if( nSize<4 ) nSize = 4;
@@ -70713,7 +68530,7 @@ static u16 cellSizePtr(MemPage *pPage, u8 *pCell){
int minLocal = pPage->minLocal;
nSize = minLocal + (nSize - minLocal) % (pPage->pBt->usableSize - 4);
testcase( nSize==pPage->maxLocal );
- testcase( nSize==pPage->maxLocal+1 );
+ testcase( nSize==(u32)pPage->maxLocal+1 );
if( nSize>pPage->maxLocal ){
nSize = minLocal;
}
@@ -70743,6 +68560,58 @@ static u16 cellSizePtrNoPayload(MemPage *pPage, u8 *pCell){
assert( debuginfo.nSize==(u16)(pIter - pCell) || CORRUPT_DB );
return (u16)(pIter - pCell);
}
+static u16 cellSizePtrTableLeaf(MemPage *pPage, u8 *pCell){
+ u8 *pIter = pCell; /* For looping over bytes of pCell */
+ u8 *pEnd; /* End mark for a varint */
+ u32 nSize; /* Size value to return */
+
+#ifdef SQLITE_DEBUG
+ /* The value returned by this function should always be the same as
+ ** the (CellInfo.nSize) value found by doing a full parse of the
+ ** cell. If SQLITE_DEBUG is defined, an assert() at the bottom of
+ ** this function verifies that this invariant is not violated. */
+ CellInfo debuginfo;
+ pPage->xParseCell(pPage, pCell, &debuginfo);
+#endif
+
+ nSize = *pIter;
+ if( nSize>=0x80 ){
+ pEnd = &pIter[8];
+ nSize &= 0x7f;
+ do{
+ nSize = (nSize<<7) | (*++pIter & 0x7f);
+ }while( *(pIter)>=0x80 && pIter<pEnd );
+ }
+ pIter++;
+ /* pIter now points at the 64-bit integer key value, a variable length
+ ** integer. The following block moves pIter to point at the first byte
+ ** past the end of the key value. */
+ if( (*pIter++)&0x80
+ && (*pIter++)&0x80
+ && (*pIter++)&0x80
+ && (*pIter++)&0x80
+ && (*pIter++)&0x80
+ && (*pIter++)&0x80
+ && (*pIter++)&0x80
+ && (*pIter++)&0x80 ){ pIter++; }
+ testcase( nSize==pPage->maxLocal );
+ testcase( nSize==(u32)pPage->maxLocal+1 );
+ if( nSize<=pPage->maxLocal ){
+ nSize += (u32)(pIter - pCell);
+ if( nSize<4 ) nSize = 4;
+ }else{
+ int minLocal = pPage->minLocal;
+ nSize = minLocal + (nSize - minLocal) % (pPage->pBt->usableSize - 4);
+ testcase( nSize==pPage->maxLocal );
+ testcase( nSize==(u32)pPage->maxLocal+1 );
+ if( nSize>pPage->maxLocal ){
+ nSize = minLocal;
+ }
+ nSize += 4 + (u16)(pIter - pCell);
+ }
+ assert( nSize==debuginfo.nSize || CORRUPT_DB );
+ return (u16)nSize;
+}
#ifdef SQLITE_DEBUG
@@ -70756,7 +68625,7 @@ static u16 cellSize(MemPage *pPage, int iCell){
#ifndef SQLITE_OMIT_AUTOVACUUM
/*
** The cell pCell is currently part of page pSrc but will ultimately be part
-** of pPage. (pSrc and pPager are often the same.) If pCell contains a
+** of pPage. (pSrc and pPage are often the same.) If pCell contains a
** pointer to an overflow page, insert an entry into the pointer-map for
** the overflow page that will be valid after pCell has been moved to pPage.
*/
@@ -70805,6 +68674,7 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){
unsigned char *src; /* Source of content */
int iCellFirst; /* First allowable cell index */
int iCellLast; /* Last possible cell index */
+ int iCellStart; /* First cell offset in input */
assert( sqlcipher_sqlite3PagerIswriteable(pPage->pDbPage) );
assert( pPage->pBt!=0 );
@@ -70846,7 +68716,7 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){
if( iFree2+sz2 > usableSize ) return SQLITE_CORRUPT_PAGE(pPage);
memmove(&data[iFree+sz+sz2], &data[iFree+sz], iFree2-(iFree+sz));
sz += sz2;
- }else if( NEVER(iFree+sz>usableSize) ){
+ }else if( iFree+sz>usableSize ){
return SQLITE_CORRUPT_PAGE(pPage);
}
@@ -70865,6 +68735,7 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){
cbrk = usableSize;
iCellLast = usableSize - 4;
+ iCellStart = get2byte(&data[hdr+5]);
for(i=0; i<nCell; i++){
u8 *pAddr; /* The i-th cell pointer */
pAddr = &data[cellOffset + i*2];
@@ -70874,25 +68745,23 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){
/* These conditions have already been verified in btreeInitPage()
** if PRAGMA cell_size_check=ON.
*/
- if( pc<iCellFirst || pc>iCellLast ){
+ if( pc<iCellStart || pc>iCellLast ){
return SQLITE_CORRUPT_PAGE(pPage);
}
- assert( pc>=iCellFirst && pc<=iCellLast );
+ assert( pc>=iCellStart && pc<=iCellLast );
size = pPage->xCellSize(pPage, &src[pc]);
cbrk -= size;
- if( cbrk<iCellFirst || pc+size>usableSize ){
+ if( cbrk<iCellStart || pc+size>usableSize ){
return SQLITE_CORRUPT_PAGE(pPage);
}
- assert( cbrk+size<=usableSize && cbrk>=iCellFirst );
+ assert( cbrk+size<=usableSize && cbrk>=iCellStart );
testcase( cbrk+size==usableSize );
testcase( pc+size==usableSize );
put2byte(pAddr, cbrk);
if( temp==0 ){
- int x;
if( cbrk==pc ) continue;
temp = sqlcipher_sqlite3PagerTempSpace(pPage->pBt->pPager);
- x = get2byte(&data[hdr+5]);
- memcpy(&temp[x], &data[x], (cbrk+size) - x);
+ memcpy(&temp[iCellStart], &data[iCellStart], usableSize - iCellStart);
src = temp;
}
memcpy(&data[cbrk], &src[pc], size);
@@ -70931,7 +68800,8 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){
const int hdr = pPg->hdrOffset; /* Offset to page header */
u8 * const aData = pPg->aData; /* Page data */
int iAddr = hdr + 1; /* Address of ptr to pc */
- int pc = get2byte(&aData[iAddr]); /* Address of a free slot */
+ u8 *pTmp = &aData[iAddr]; /* Temporary ptr into aData[] */
+ int pc = get2byte(pTmp); /* Address of a free slot */
int x; /* Excess size of the slot */
int maxPC = pPg->pBt->usableSize - nByte; /* Max address for a usable slot */
int size; /* Size of the free slot */
@@ -70941,7 +68811,8 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){
/* EVIDENCE-OF: R-22710-53328 The third and fourth bytes of each
** freeblock form a big-endian integer which is the size of the freeblock
** in bytes, including the 4-byte header. */
- size = get2byte(&aData[pc+2]);
+ pTmp = &aData[pc+2];
+ size = get2byte(pTmp);
if( (x = size - nByte)>=0 ){
testcase( x==4 );
testcase( x==3 );
@@ -70954,6 +68825,8 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){
** fragmented bytes within the page. */
memcpy(&aData[iAddr], &aData[pc], 2);
aData[hdr+7] += (u8)x;
+ testcase( pc+x>maxPC );
+ return &aData[pc];
}else if( x+pc > maxPC ){
/* This slot extends off the end of the usable part of the page */
*pRc = SQLITE_CORRUPT_PAGE(pPg);
@@ -70966,7 +68839,8 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){
return &aData[pc + x];
}
iAddr = pc;
- pc = get2byte(&aData[pc]);
+ pTmp = &aData[pc];
+ pc = get2byte(pTmp);
if( pc<=iAddr+size ){
if( pc ){
/* The next slot in the chain is not past the end of the current slot */
@@ -71000,6 +68874,7 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
u8 * const data = pPage->aData; /* Local cache of pPage->aData */
int top; /* First byte of cell content area */
int rc = SQLITE_OK; /* Integer return code */
+ u8 *pTmp; /* Temp ptr into data[] */
int gap; /* First byte of gap between cell pointers and cell content */
assert( sqlcipher_sqlite3PagerIswriteable(pPage->pDbPage) );
@@ -71018,7 +68893,8 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
** then the cell content offset of an empty page wants to be 65536.
** However, that integer is too large to be stored in a 2-byte unsigned
** integer, so a value of 0 is used in its place. */
- top = get2byte(&data[hdr+5]);
+ pTmp = &data[hdr+5];
+ top = get2byte(pTmp);
assert( top<=(int)pPage->pBt->usableSize ); /* by btreeComputeFreeSpace() */
if( gap>top ){
if( top==0 && pPage->pBt->usableSize==65536 ){
@@ -71041,7 +68917,7 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
int g2;
assert( pSpace+nByte<=data+pPage->pBt->usableSize );
*pIdx = g2 = (int)(pSpace-data);
- if( NEVER(g2<=gap) ){
+ if( g2<=gap ){
return SQLITE_CORRUPT_PAGE(pPage);
}else{
return SQLITE_OK;
@@ -71100,6 +68976,7 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
u16 x; /* Offset to cell content area */
u32 iEnd = iStart + iSize; /* First byte past the iStart buffer */
unsigned char *data = pPage->aData; /* Page content */
+ u8 *pTmp; /* Temporary ptr into data[] */
assert( pPage->pBt!=0 );
assert( sqlcipher_sqlite3PagerIswriteable(pPage->pDbPage) );
@@ -71127,7 +69004,7 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
if( iFreeBlk>pPage->pBt->usableSize-4 ){ /* TH3: corrupt081.100 */
return SQLITE_CORRUPT_PAGE(pPage);
}
- assert( iFreeBlk>iPtr || iFreeBlk==0 );
+ assert( iFreeBlk>iPtr || iFreeBlk==0 || CORRUPT_DB );
/* At this point:
** iFreeBlk: First freeblock after iStart, or zero if none
@@ -71162,7 +69039,8 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
if( nFrag>data[hdr+7] ) return SQLITE_CORRUPT_PAGE(pPage);
data[hdr+7] -= nFrag;
}
- x = get2byte(&data[hdr+5]);
+ pTmp = &data[hdr+5];
+ x = get2byte(pTmp);
if( iStart<=x ){
/* The new freeblock is at the beginning of the cell content area,
** so just extend the cell content area rather than create another
@@ -71206,7 +69084,6 @@ static int decodeFlags(MemPage *pPage, int flagByte){
pPage->leaf = (u8)(flagByte>>3); assert( PTF_LEAF == 1<<3 );
flagByte &= ~PTF_LEAF;
pPage->childPtrSize = 4-4*pPage->leaf;
- pPage->xCellSize = cellSizePtr;
pBt = pPage->pBt;
if( flagByte==(PTF_LEAFDATA | PTF_INTKEY) ){
/* EVIDENCE-OF: R-07291-35328 A value of 5 (0x05) means the page is an
@@ -71218,6 +69095,7 @@ static int decodeFlags(MemPage *pPage, int flagByte){
pPage->intKey = 1;
if( pPage->leaf ){
pPage->intKeyLeaf = 1;
+ pPage->xCellSize = cellSizePtrTableLeaf;
pPage->xParseCell = btreeParseCellPtr;
}else{
pPage->intKeyLeaf = 0;
@@ -71235,12 +69113,17 @@ static int decodeFlags(MemPage *pPage, int flagByte){
assert( (PTF_ZERODATA|PTF_LEAF)==10 );
pPage->intKey = 0;
pPage->intKeyLeaf = 0;
+ pPage->xCellSize = cellSizePtr;
pPage->xParseCell = btreeParseCellPtrIndex;
pPage->maxLocal = pBt->maxLocal;
pPage->minLocal = pBt->minLocal;
}else{
/* EVIDENCE-OF: R-47608-56469 Any other value for the b-tree page type is
** an error. */
+ pPage->intKey = 0;
+ pPage->intKeyLeaf = 0;
+ pPage->xCellSize = cellSizePtr;
+ pPage->xParseCell = btreeParseCellPtrIndex;
return SQLITE_CORRUPT_PAGE(pPage);
}
pPage->max1bytePayload = pBt->max1bytePayload;
@@ -71398,7 +69281,7 @@ static int btreeInitPage(MemPage *pPage){
pPage->nOverflow = 0;
pPage->cellOffset = pPage->hdrOffset + 8 + pPage->childPtrSize;
pPage->aCellIdx = data + pPage->childPtrSize + 8;
- pPage->aDataEnd = pPage->aData + pBt->usableSize;
+ pPage->aDataEnd = pPage->aData + pBt->pageSize;
pPage->aDataOfst = pPage->aData + pPage->childPtrSize;
/* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the
** number of cells on the page. */
@@ -71433,7 +69316,7 @@ static void zeroPage(MemPage *pPage, int flags){
u8 hdr = pPage->hdrOffset;
u16 first;
- assert( sqlcipher_sqlite3PagerPagenumber(pPage->pDbPage)==pPage->pgno );
+ assert( sqlcipher_sqlite3PagerPagenumber(pPage->pDbPage)==pPage->pgno || CORRUPT_DB );
assert( sqlcipher_sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage );
assert( sqlcipher_sqlite3PagerGetData(pPage->pDbPage) == data );
assert( sqlcipher_sqlite3PagerIswriteable(pPage->pDbPage) );
@@ -71449,7 +69332,7 @@ static void zeroPage(MemPage *pPage, int flags){
pPage->nFree = (u16)(pBt->usableSize - first);
decodeFlags(pPage, flags);
pPage->cellOffset = first;
- pPage->aDataEnd = &data[pBt->usableSize];
+ pPage->aDataEnd = &data[pBt->pageSize];
pPage->aCellIdx = &data[first];
pPage->aDataOfst = &data[pPage->childPtrSize];
pPage->nOverflow = 0;
@@ -71575,7 +69458,7 @@ static int getAndInitPage(
goto getAndInitPage_error2;
}
}
- assert( (*ppPage)->pgno==pgno );
+ assert( (*ppPage)->pgno==pgno || CORRUPT_DB );
assert( (*ppPage)->aData==sqlcipher_sqlite3PagerGetData(pDbPage) );
/* If obtaining a child page for a cursor, we must verify that the page is
@@ -71594,7 +69477,9 @@ getAndInitPage_error1:
pCur->pPage = pCur->apPage[pCur->iPage];
}
testcase( pgno==0 );
- assert( pgno!=0 || rc==SQLITE_CORRUPT );
+ assert( pgno!=0 || rc==SQLITE_CORRUPT
+ || rc==SQLITE_IOERR_NOMEM
+ || rc==SQLITE_NOMEM );
return rc;
}
@@ -72052,30 +69937,38 @@ static int removeFromSharingList(BtShared *pBt){
** MX_CELL_SIZE(pBt) bytes with a 4-byte prefix for a left-child
** pointer.
*/
-static void allocateTempSpace(BtShared *pBt){
- if( !pBt->pTmpSpace ){
- pBt->pTmpSpace = sqlcipher_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.
- **
- ** Also: Provide four bytes of initialized space before the
- ** beginning of pTmpSpace as an area available to prepend the
- ** left-child pointer to the beginning of a cell.
- */
- if( pBt->pTmpSpace ){
- memset(pBt->pTmpSpace, 0, 8);
- pBt->pTmpSpace += 4;
- }
+static SQLITE_NOINLINE int allocateTempSpace(BtShared *pBt){
+ assert( pBt!=0 );
+ assert( pBt->pTmpSpace==0 );
+ /* This routine is called only by btreeCursor() when allocating the
+ ** first write cursor for the BtShared object */
+ assert( pBt->pCursor!=0 && (pBt->pCursor->curFlags & BTCF_WriteFlag)!=0 );
+ pBt->pTmpSpace = sqlcipher_sqlite3PageMalloc( pBt->pageSize );
+ if( pBt->pTmpSpace==0 ){
+ BtCursor *pCur = pBt->pCursor;
+ pBt->pCursor = pCur->pNext; /* Unlink the cursor */
+ memset(pCur, 0, sizeof(*pCur));
+ return SQLITE_NOMEM_BKPT;
}
+
+ /* 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.
+ **
+ ** Also: Provide four bytes of initialized space before the
+ ** beginning of pTmpSpace as an area available to prepend the
+ ** left-child pointer to the beginning of a cell.
+ */
+ memset(pBt->pTmpSpace, 0, 8);
+ pBt->pTmpSpace += 4;
+ return SQLITE_OK;
}
/*
@@ -72094,19 +69987,23 @@ static void freeTempSpace(BtShared *pBt){
*/
SQLITE_PRIVATE int sqlcipher_sqlite3BtreeClose(Btree *p){
BtShared *pBt = p->pBt;
- BtCursor *pCur;
/* Close all cursors opened via this handle. */
assert( sqlcipher_sqlite3_mutex_held(p->db->mutex) );
sqlcipher_sqlite3BtreeEnter(p);
- pCur = pBt->pCursor;
- while( pCur ){
- BtCursor *pTmp = pCur;
- pCur = pCur->pNext;
- if( pTmp->pBtree==p ){
- sqlcipher_sqlite3BtreeCloseCursor(pTmp);
+
+ /* Verify that no other cursors have this Btree open */
+#ifdef SQLITE_DEBUG
+ {
+ BtCursor *pCur = pBt->pCursor;
+ while( pCur ){
+ BtCursor *pTmp = pCur;
+ pCur = pCur->pNext;
+ assert( pTmp->pBtree!=p );
+
}
}
+#endif
/* Rollback any active transaction and free the handle structure.
** The call to sqlcipher_sqlite3BtreeRollback() drops any table-locks held by
@@ -72258,6 +70155,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3BtreeSetPageSize(Btree *p, int pageSize, int
((pageSize-1)&pageSize)==0 ){
assert( (pageSize & 7)==0 );
assert( !pBt->pCursor );
+ if( nReserve>32 && pageSize==512 ) pageSize = 1024;
pBt->pageSize = (u32)pageSize;
freeTempSpace(pBt);
}
@@ -72449,7 +70347,6 @@ static int lockBtree(BtShared *pBt){
MemPage *pPage1; /* Page 1 of the database file */
u32 nPage; /* Number of pages in the database */
u32 nPageFile = 0; /* Number of pages in the database file */
- u32 nPageHeader; /* Number of pages in the database according to hdr */
assert( sqlcipher_sqlite3_mutex_held(pBt->mutex) );
assert( pBt->pPage1==0 );
@@ -72461,7 +70358,7 @@ static int lockBtree(BtShared *pBt){
/* Do some checking to help insure the file we opened really is
** a valid database file.
*/
- nPage = nPageHeader = get4byte(28+(u8*)pPage1->aData);
+ nPage = get4byte(28+(u8*)pPage1->aData);
sqlcipher_sqlite3PagerPagecount(pBt->pPager, (int*)&nPageFile);
if( nPage==0 || memcmp(24+(u8*)pPage1->aData, 92+(u8*)pPage1->aData,4)!=0 ){
nPage = nPageFile;
@@ -72496,7 +70393,7 @@ static int lockBtree(BtShared *pBt){
goto page1_init_failed;
}
- /* If the write version is set to 2, this database should be accessed
+ /* If the read version is set to 2, this database should be accessed
** in WAL mode. If the log is not already open, open it now. Then
** return SQLITE_OK and return without populating BtShared.pPage1.
** The caller detects this and calls this function again. This is
@@ -72568,9 +70465,13 @@ static int lockBtree(BtShared *pBt){
pageSize-usableSize);
return rc;
}
- if( sqlcipher_sqlite3WritableSchema(pBt->db)==0 && nPage>nPageFile ){
- rc = SQLITE_CORRUPT_BKPT;
- goto page1_init_failed;
+ if( nPage>nPageFile ){
+ if( sqlcipher_sqlite3WritableSchema(pBt->db)==0 ){
+ rc = SQLITE_CORRUPT_BKPT;
+ goto page1_init_failed;
+ }else{
+ nPage = nPageFile;
+ }
}
/* EVIDENCE-OF: R-28312-64704 However, the usable size is not allowed to
** be less than 480. In other words, if the page size is 512, then the
@@ -73200,12 +71101,17 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg, int bCommit){
}
do {
MemPage *pFreePg;
+ Pgno dbSize = btreePagecount(pBt);
rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iNear, eMode);
if( rc!=SQLITE_OK ){
releasePage(pLastPg);
return rc;
}
releasePage(pFreePg);
+ if( iFreePg>dbSize ){
+ releasePage(pLastPg);
+ return SQLITE_CORRUPT_BKPT;
+ }
}while( bCommit && iFreePg>nFin );
assert( iFreePg<iLastPg );
@@ -73294,16 +71200,18 @@ SQLITE_PRIVATE int sqlcipher_sqlite3BtreeIncrVacuum(Btree *p){
/*
** This routine is called prior to sqlcipher_sqlite3PagerCommit when a transaction
** 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.
-** i.e. the database has been reorganized so that only the first *pnTrunc
-** pages are in use.
*/
-static int autoVacuumCommit(BtShared *pBt){
+static int autoVacuumCommit(Btree *p){
int rc = SQLITE_OK;
- Pager *pPager = pBt->pPager;
- VVA_ONLY( int nRef = sqlcipher_sqlite3PagerRefcount(pPager); )
+ Pager *pPager;
+ BtShared *pBt;
+ sqlcipher_sqlite3 *db;
+ VVA_ONLY( int nRef );
+
+ assert( p!=0 );
+ pBt = p->pBt;
+ pPager = pBt->pPager;
+ VVA_ONLY( nRef = sqlcipher_sqlite3PagerRefcount(pPager); )
assert( sqlcipher_sqlite3_mutex_held(pBt->mutex) );
invalidateAllOverflowCache(pBt);
@@ -73311,6 +71219,7 @@ static int autoVacuumCommit(BtShared *pBt){
if( !pBt->incrVacuum ){
Pgno nFin; /* Number of pages in database after autovacuuming */
Pgno nFree; /* Number of pages on the freelist initially */
+ Pgno nVac; /* Number of pages to vacuum */
Pgno iFree; /* The next page to be freed */
Pgno nOrig; /* Database size before freeing */
@@ -73324,18 +71233,42 @@ static int autoVacuumCommit(BtShared *pBt){
}
nFree = get4byte(&pBt->pPage1->aData[36]);
- nFin = finalDbSize(pBt, nOrig, nFree);
+ db = p->db;
+ if( db->xAutovacPages ){
+ int iDb;
+ for(iDb=0; ALWAYS(iDb<db->nDb); iDb++){
+ if( db->aDb[iDb].pBt==p ) break;
+ }
+ nVac = db->xAutovacPages(
+ db->pAutovacPagesArg,
+ db->aDb[iDb].zDbSName,
+ nOrig,
+ nFree,
+ pBt->pageSize
+ );
+ if( nVac>nFree ){
+ nVac = nFree;
+ }
+ if( nVac==0 ){
+ return SQLITE_OK;
+ }
+ }else{
+ nVac = nFree;
+ }
+ nFin = finalDbSize(pBt, nOrig, nVac);
if( nFin>nOrig ) return SQLITE_CORRUPT_BKPT;
if( nFin<nOrig ){
rc = saveAllCursors(pBt, 0, 0);
}
for(iFree=nOrig; iFree>nFin && rc==SQLITE_OK; iFree--){
- rc = incrVacuumStep(pBt, nFin, iFree, 1);
+ rc = incrVacuumStep(pBt, nFin, iFree, nVac==nFree);
}
if( (rc==SQLITE_DONE || rc==SQLITE_OK) && nFree>0 ){
rc = sqlcipher_sqlite3PagerWrite(pBt->pPage1->pDbPage);
- put4byte(&pBt->pPage1->aData[32], 0);
- put4byte(&pBt->pPage1->aData[36], 0);
+ if( nVac==nFree ){
+ put4byte(&pBt->pPage1->aData[32], 0);
+ put4byte(&pBt->pPage1->aData[36], 0);
+ }
put4byte(&pBt->pPage1->aData[28], nFin);
pBt->bDoTruncate = 1;
pBt->nPage = nFin;
@@ -73386,7 +71319,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3BtreeCommitPhaseOne(Btree *p, const char *zS
sqlcipher_sqlite3BtreeEnter(p);
#ifndef SQLITE_OMIT_AUTOVACUUM
if( pBt->autoVacuum ){
- rc = autoVacuumCommit(pBt);
+ rc = autoVacuumCommit(p);
if( rc!=SQLITE_OK ){
sqlcipher_sqlite3BtreeLeave(p);
return rc;
@@ -73487,7 +71420,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3BtreeCommitPhaseTwo(Btree *p, int bCleanup){
sqlcipher_sqlite3BtreeLeave(p);
return rc;
}
- p->iDataVersion--; /* Compensate for pPager->iDataVersion++; */
+ p->iBDataVersion--; /* Compensate for pPager->iDataVersion++; */
pBt->inTransaction = TRANS_READ;
btreeClearHasContent(pBt);
}
@@ -73573,7 +71506,7 @@ static void btreeSetNPage(BtShared *pBt, MemPage *pPage1){
int nPage = get4byte(&pPage1->aData[28]);
testcase( nPage==0 );
if( nPage==0 ) sqlcipher_sqlite3PagerPagecount(pBt->pPager, &nPage);
- testcase( pBt->nPage!=nPage );
+ testcase( pBt->nPage!=(u32)nPage );
pBt->nPage = nPage;
}
@@ -73785,10 +71718,6 @@ static int btreeCursor(
assert( pBt->pPage1 && pBt->pPage1->aData );
assert( wrFlag==0 || (pBt->btsFlags & BTS_READ_ONLY)==0 );
- if( wrFlag ){
- allocateTempSpace(pBt);
- if( pBt->pTmpSpace==0 ) return SQLITE_NOMEM_BKPT;
- }
if( iTable<=1 ){
if( iTable<1 ){
return SQLITE_CORRUPT_BKPT;
@@ -73805,19 +71734,25 @@ static int btreeCursor(
pCur->pKeyInfo = pKeyInfo;
pCur->pBtree = p;
pCur->pBt = pBt;
- pCur->curFlags = wrFlag ? BTCF_WriteFlag : 0;
- pCur->curPagerFlags = wrFlag ? 0 : PAGER_GET_READONLY;
+ pCur->curFlags = 0;
/* If there are two or more cursors on the same btree, then all such
** cursors *must* have the BTCF_Multiple flag set. */
for(pX=pBt->pCursor; pX; pX=pX->pNext){
if( pX->pgnoRoot==iTable ){
pX->curFlags |= BTCF_Multiple;
- pCur->curFlags |= BTCF_Multiple;
+ pCur->curFlags = BTCF_Multiple;
}
}
+ pCur->eState = CURSOR_INVALID;
pCur->pNext = pBt->pCursor;
pBt->pCursor = pCur;
- pCur->eState = CURSOR_INVALID;
+ if( wrFlag ){
+ pCur->curFlags |= BTCF_WriteFlag;
+ pCur->curPagerFlags = 0;
+ if( pBt->pTmpSpace==0 ) return allocateTempSpace(pBt);
+ }else{
+ pCur->curPagerFlags = PAGER_GET_READONLY;
+ }
return SQLITE_OK;
}
static int btreeCursorWithLock(
@@ -73897,7 +71832,14 @@ SQLITE_PRIVATE int sqlcipher_sqlite3BtreeCloseCursor(BtCursor *pCur){
unlockBtreeIfUnused(pBt);
sqlcipher_sqlite3_free(pCur->aOverflow);
sqlcipher_sqlite3_free(pCur->pKey);
- sqlcipher_sqlite3BtreeLeave(pBtree);
+ if( (pBt->openFlags & BTREE_SINGLE) && pBt->pCursor==0 ){
+ /* Since the BtShared is not sharable, there is no need to
+ ** worry about the missing sqlcipher_sqlite3BtreeLeave() call here. */
+ assert( pBtree->sharable==0 );
+ sqlcipher_sqlite3BtreeClose(pBtree);
+ }else{
+ sqlcipher_sqlite3BtreeLeave(pBtree);
+ }
pCur->pBtree = 0;
}
return SQLITE_OK;
@@ -74184,7 +72126,9 @@ static int accessPayload(
assert( pPage );
assert( eOp==0 || eOp==1 );
assert( pCur->eState==CURSOR_VALID );
- assert( pCur->ix<pPage->nCell );
+ if( pCur->ix>=pPage->nCell ){
+ return SQLITE_CORRUPT_PAGE(pPage);
+ }
assert( cursorHoldsMutex(pCur) );
getCellInfo(pCur);
@@ -74371,7 +72315,6 @@ SQLITE_PRIVATE int sqlcipher_sqlite3BtreePayload(BtCursor *pCur, u32 offset, u32
assert( cursorHoldsMutex(pCur) );
assert( pCur->eState==CURSOR_VALID );
assert( pCur->iPage>=0 && pCur->pPage );
- assert( pCur->ix<pCur->pPage->nCell );
return accessPayload(pCur, offset, amt, (unsigned char*)pBuf, 0);
}
@@ -74433,7 +72376,7 @@ static const void *fetchPayload(
assert( pCur->eState==CURSOR_VALID );
assert( sqlcipher_sqlite3_mutex_held(pCur->pBtree->db->mutex) );
assert( cursorOwnsBtShared(pCur) );
- assert( pCur->ix<pCur->pPage->nCell );
+ assert( pCur->ix<pCur->pPage->nCell || CORRUPT_DB );
assert( pCur->info.nSize>0 );
assert( pCur->info.pPayload>pCur->pPage->aData || CORRUPT_DB );
assert( pCur->info.pPayload<pCur->pPage->aDataEnd ||CORRUPT_DB);
@@ -74584,7 +72527,7 @@ static int moveToRoot(BtCursor *pCur){
while( --pCur->iPage ){
releasePageNotNull(pCur->apPage[pCur->iPage]);
}
- pCur->pPage = pCur->apPage[0];
+ pRoot = pCur->pPage = pCur->apPage[0];
goto skip_init;
}
}else if( pCur->pgnoRoot==0 ){
@@ -74609,7 +72552,7 @@ static int moveToRoot(BtCursor *pCur){
pCur->curIntKey = pCur->pPage->intKey;
}
pRoot = pCur->pPage;
- assert( pRoot->pgno==pCur->pgnoRoot );
+ assert( pRoot->pgno==pCur->pgnoRoot || CORRUPT_DB );
/* 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
@@ -74631,7 +72574,6 @@ skip_init:
pCur->info.nSize = 0;
pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidNKey|BTCF_ValidOvfl);
- pRoot = pCur->pPage;
if( pRoot->nCell>0 ){
pCur->eState = CURSOR_VALID;
}else if( !pRoot->leaf ){
@@ -74739,7 +72681,9 @@ SQLITE_PRIVATE int sqlcipher_sqlite3BtreeLast(BtCursor *pCur, int *pRes){
for(ii=0; ii<pCur->iPage; ii++){
assert( pCur->aiIdx[ii]==pCur->apPage[ii]->nCell );
}
- assert( pCur->ix==pCur->pPage->nCell-1 );
+ assert( pCur->ix==pCur->pPage->nCell-1 || CORRUPT_DB );
+ testcase( pCur->ix!=pCur->pPage->nCell-1 );
+ /* ^-- dbsqlfuzz b92b72e4de80b5140c30ab71372ca719b8feb618 */
assert( pCur->pPage->leaf );
#endif
*pRes = 0;
@@ -74764,12 +72708,8 @@ SQLITE_PRIVATE int sqlcipher_sqlite3BtreeLast(BtCursor *pCur, int *pRes){
return rc;
}
-/* Move the cursor so that it points to an entry near the key
-** specified by pIdxKey or intKey. Return a success code.
-**
-** For INTKEY tables, the intKey parameter is used. pIdxKey
-** must be NULL. For index tables, pIdxKey is used and intKey
-** is ignored.
+/* Move the cursor so that it points to an entry in a table (a.k.a INTKEY)
+** table near the key intKey. Return a success code.
**
** If an exact match is not found, then the cursor is always
** left pointing at a leaf page which would hold the entry if it
@@ -74782,39 +72722,32 @@ SQLITE_PRIVATE int sqlcipher_sqlite3BtreeLast(BtCursor *pCur, int *pRes){
** *pRes is as follows:
**
** *pRes<0 The cursor is left pointing at an entry that
-** is smaller than intKey/pIdxKey or if the table is empty
+** is smaller than intKey or if the table is empty
** and the cursor is therefore left point to nothing.
**
** *pRes==0 The cursor is left pointing at an entry that
-** exactly matches intKey/pIdxKey.
+** exactly matches intKey.
**
** *pRes>0 The cursor is left pointing at an entry that
-** is larger than intKey/pIdxKey.
-**
-** For index tables, the pIdxKey->eqSeen field is set to 1 if there
-** exists an entry in the table that exactly matches pIdxKey.
+** is larger than intKey.
*/
-SQLITE_PRIVATE int sqlcipher_sqlite3BtreeMovetoUnpacked(
+SQLITE_PRIVATE int sqlcipher_sqlite3BtreeTableMoveto(
BtCursor *pCur, /* The cursor to be moved */
- UnpackedRecord *pIdxKey, /* Unpacked index key */
i64 intKey, /* The table key */
int biasRight, /* If true, bias the search to the high end */
int *pRes /* Write search results here */
){
int rc;
- RecordCompare xRecordCompare;
assert( cursorOwnsBtShared(pCur) );
assert( sqlcipher_sqlite3_mutex_held(pCur->pBtree->db->mutex) );
assert( pRes );
- assert( (pIdxKey==0)==(pCur->pKeyInfo==0) );
- assert( pCur->eState!=CURSOR_VALID || (pIdxKey==0)==(pCur->curIntKey!=0) );
+ assert( pCur->pKeyInfo==0 );
+ assert( pCur->eState!=CURSOR_VALID || pCur->curIntKey!=0 );
/* If the cursor is already positioned at the point we are trying
** to move to, then just return without doing any work */
- if( pIdxKey==0
- && pCur->eState==CURSOR_VALID && (pCur->curFlags & BTCF_ValidNKey)!=0
- ){
+ if( pCur->eState==CURSOR_VALID && (pCur->curFlags & BTCF_ValidNKey)!=0 ){
if( pCur->info.nKey==intKey ){
*pRes = 0;
return SQLITE_OK;
@@ -74836,9 +72769,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3BtreeMovetoUnpacked(
if( pCur->info.nKey==intKey ){
return SQLITE_OK;
}
- }else if( rc==SQLITE_DONE ){
- rc = SQLITE_OK;
- }else{
+ }else if( rc!=SQLITE_DONE ){
return rc;
}
}
@@ -74849,17 +72780,6 @@ SQLITE_PRIVATE int sqlcipher_sqlite3BtreeMovetoUnpacked(
pCur->pBtree->nSeek++; /* Performance measurement during testing */
#endif
- if( pIdxKey ){
- xRecordCompare = sqlcipher_sqlite3VdbeFindCompare(pIdxKey);
- pIdxKey->errCode = 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 ){
if( rc==SQLITE_EMPTY ){
@@ -74874,7 +72794,8 @@ SQLITE_PRIVATE int sqlcipher_sqlite3BtreeMovetoUnpacked(
assert( pCur->eState==CURSOR_VALID );
assert( pCur->pPage->nCell > 0 );
assert( pCur->iPage==0 || pCur->apPage[0]->intKey==pCur->curIntKey );
- assert( pCur->curIntKey || pIdxKey );
+ assert( pCur->curIntKey );
+
for(;;){
int lwr, upr, idx, c;
Pgno chldPg;
@@ -74888,144 +72809,348 @@ SQLITE_PRIVATE int sqlcipher_sqlite3BtreeMovetoUnpacked(
** be the right kind (index or table) of b-tree page. Otherwise
** a moveToChild() or moveToRoot() call would have detected corruption. */
assert( pPage->nCell>0 );
- assert( pPage->intKey==(pIdxKey==0) );
+ assert( pPage->intKey );
lwr = 0;
upr = pPage->nCell-1;
assert( biasRight==0 || biasRight==1 );
idx = upr>>(1-biasRight); /* idx = biasRight ? upr : (lwr+upr)/2; */
- pCur->ix = (u16)idx;
- if( xRecordCompare==0 ){
- for(;;){
- i64 nCellKey;
- pCell = findCellPastPtr(pPage, idx);
- if( pPage->intKeyLeaf ){
- while( 0x80 <= *(pCell++) ){
- if( pCell>=pPage->aDataEnd ){
- return SQLITE_CORRUPT_PAGE(pPage);
- }
+ for(;;){
+ i64 nCellKey;
+ pCell = findCellPastPtr(pPage, idx);
+ if( pPage->intKeyLeaf ){
+ while( 0x80 <= *(pCell++) ){
+ if( pCell>=pPage->aDataEnd ){
+ return SQLITE_CORRUPT_PAGE(pPage);
}
}
- getVarint(pCell, (u64*)&nCellKey);
- 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; }
+ }
+ getVarint(pCell, (u64*)&nCellKey);
+ 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 );
+ pCur->ix = (u16)idx;
+ if( !pPage->leaf ){
+ lwr = idx;
+ goto moveto_table_next_layer;
}else{
- assert( nCellKey==intKey );
- pCur->ix = (u16)idx;
- if( !pPage->leaf ){
- lwr = idx;
- goto moveto_next_layer;
- }else{
- pCur->curFlags |= BTCF_ValidNKey;
- pCur->info.nKey = nCellKey;
- pCur->info.nSize = 0;
- *pRes = 0;
- return SQLITE_OK;
- }
+ pCur->curFlags |= BTCF_ValidNKey;
+ pCur->info.nKey = nCellKey;
+ pCur->info.nSize = 0;
+ *pRes = 0;
+ return SQLITE_OK;
}
- assert( lwr+upr>=0 );
- idx = (lwr+upr)>>1; /* idx = (lwr+upr)/2; */
}
+ assert( lwr+upr>=0 );
+ idx = (lwr+upr)>>1; /* idx = (lwr+upr)/2; */
+ }
+ assert( lwr==upr+1 || !pPage->leaf );
+ assert( pPage->isInit );
+ if( pPage->leaf ){
+ assert( pCur->ix<pCur->pPage->nCell );
+ pCur->ix = (u16)idx;
+ *pRes = c;
+ rc = SQLITE_OK;
+ goto moveto_table_finish;
+ }
+moveto_table_next_layer:
+ if( lwr>=pPage->nCell ){
+ chldPg = get4byte(&pPage->aData[pPage->hdrOffset+8]);
}else{
- for(;;){
- int nCell; /* Size of the pCell cell in bytes */
- pCell = findCellPastPtr(pPage, idx);
-
- /* 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
- ** varint. This information is used to attempt to avoid parsing
- ** the entire cell by checking for the cases where the record is
- ** stored entirely within the b-tree page by inspecting the first
- ** 2 bytes of the cell.
- */
- 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 = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey);
- }else if( !(pCell[1] & 0x80)
- && (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal
- ){
- /* 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 = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey);
- }else{
- /* The record flows over onto one or more overflow pages. In
- ** this case the whole cell needs to be parsed, a buffer allocated
- ** and accessPayload() used to retrieve the record into the
- ** buffer before VdbeRecordCompare() can be called.
- **
- ** If the record is corrupt, the xRecordCompare routine may read
- ** up to two varints past the end of the buffer. An extra 18
- ** bytes of padding is allocated at the end of the buffer in
- ** case this happens. */
- void *pCellKey;
- u8 * const pCellBody = pCell - pPage->childPtrSize;
- const int nOverrun = 18; /* Size of the overrun padding */
- pPage->xParseCell(pPage, pCellBody, &pCur->info);
- nCell = (int)pCur->info.nKey;
- testcase( nCell<0 ); /* True if key size is 2^32 or more */
- testcase( nCell==0 ); /* Invalid key size: 0x80 0x80 0x00 */
- testcase( nCell==1 ); /* Invalid key size: 0x80 0x80 0x01 */
- testcase( nCell==2 ); /* Minimum legal index key size */
- if( nCell<2 || nCell/pCur->pBt->usableSize>pCur->pBt->nPage ){
- rc = SQLITE_CORRUPT_PAGE(pPage);
- goto moveto_finish;
- }
- pCellKey = sqlcipher_sqlite3Malloc( nCell+nOverrun );
- if( pCellKey==0 ){
- rc = SQLITE_NOMEM_BKPT;
- goto moveto_finish;
- }
- pCur->ix = (u16)idx;
- rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 0);
- memset(((u8*)pCellKey)+nCell,0,nOverrun); /* Fix uninit warnings */
- pCur->curFlags &= ~BTCF_ValidOvfl;
- if( rc ){
- sqlcipher_sqlite3_free(pCellKey);
- goto moveto_finish;
- }
- c = sqlcipher_sqlite3VdbeRecordCompare(nCell, pCellKey, pIdxKey);
- sqlcipher_sqlite3_free(pCellKey);
+ chldPg = get4byte(findCell(pPage, lwr));
+ }
+ pCur->ix = (u16)lwr;
+ rc = moveToChild(pCur, chldPg);
+ if( rc ) break;
+ }
+moveto_table_finish:
+ pCur->info.nSize = 0;
+ assert( (pCur->curFlags & BTCF_ValidOvfl)==0 );
+ return rc;
+}
+
+/*
+** Compare the "idx"-th cell on the page the cursor pCur is currently
+** pointing to to pIdxKey using xRecordCompare. Return negative or
+** zero if the cell is less than or equal pIdxKey. Return positive
+** if unknown.
+**
+** Return value negative: Cell at pCur[idx] less than pIdxKey
+**
+** Return value is zero: Cell at pCur[idx] equals pIdxKey
+**
+** Return value positive: Nothing is known about the relationship
+** of the cell at pCur[idx] and pIdxKey.
+**
+** This routine is part of an optimization. It is always safe to return
+** a positive value as that will cause the optimization to be skipped.
+*/
+static int indexCellCompare(
+ BtCursor *pCur,
+ int idx,
+ UnpackedRecord *pIdxKey,
+ RecordCompare xRecordCompare
+){
+ MemPage *pPage = pCur->pPage;
+ int c;
+ int nCell; /* Size of the pCell cell in bytes */
+ u8 *pCell = findCellPastPtr(pPage, idx);
+
+ 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 = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey);
+ }else if( !(pCell[1] & 0x80)
+ && (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal
+ ){
+ /* 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 = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey);
+ }else{
+ /* If the record extends into overflow pages, do not attempt
+ ** the optimization. */
+ c = 99;
+ }
+ return c;
+}
+
+/*
+** Return true (non-zero) if pCur is current pointing to the last
+** page of a table.
+*/
+static int cursorOnLastPage(BtCursor *pCur){
+ int i;
+ assert( pCur->eState==CURSOR_VALID );
+ for(i=0; i<pCur->iPage; i++){
+ MemPage *pPage = pCur->apPage[i];
+ if( pCur->aiIdx[i]<pPage->nCell ) return 0;
+ }
+ return 1;
+}
+
+/* Move the cursor so that it points to an entry in an index table
+** near the key pIdxKey. Return a success code.
+**
+** If an exact match is not found, then the cursor is always
+** left pointing at a leaf page which would hold the entry if it
+** were present. The cursor might point to an entry that comes
+** before or after the key.
+**
+** An integer is written into *pRes which is the result of
+** comparing the key with the entry to which the cursor is
+** pointing. The meaning of the integer written into
+** *pRes is as follows:
+**
+** *pRes<0 The cursor is left pointing at an entry that
+** is smaller than pIdxKey or if the table is empty
+** and the cursor is therefore left point to nothing.
+**
+** *pRes==0 The cursor is left pointing at an entry that
+** exactly matches pIdxKey.
+**
+** *pRes>0 The cursor is left pointing at an entry that
+** is larger than pIdxKey.
+**
+** The pIdxKey->eqSeen field is set to 1 if there
+** exists an entry in the table that exactly matches pIdxKey.
+*/
+SQLITE_PRIVATE int sqlcipher_sqlite3BtreeIndexMoveto(
+ BtCursor *pCur, /* The cursor to be moved */
+ UnpackedRecord *pIdxKey, /* Unpacked index key */
+ int *pRes /* Write search results here */
+){
+ int rc;
+ RecordCompare xRecordCompare;
+
+ assert( cursorOwnsBtShared(pCur) );
+ assert( sqlcipher_sqlite3_mutex_held(pCur->pBtree->db->mutex) );
+ assert( pRes );
+ assert( pCur->pKeyInfo!=0 );
+
+#ifdef SQLITE_DEBUG
+ pCur->pBtree->nSeek++; /* Performance measurement during testing */
+#endif
+
+ xRecordCompare = sqlcipher_sqlite3VdbeFindCompare(pIdxKey);
+ pIdxKey->errCode = 0;
+ assert( pIdxKey->default_rc==1
+ || pIdxKey->default_rc==0
+ || pIdxKey->default_rc==-1
+ );
+
+
+ /* Check to see if we can skip a lot of work. Two cases:
+ **
+ ** (1) If the cursor is already pointing to the very last cell
+ ** in the table and the pIdxKey search key is greater than or
+ ** equal to that last cell, then no movement is required.
+ **
+ ** (2) If the cursor is on the last page of the table and the first
+ ** cell on that last page is less than or equal to the pIdxKey
+ ** search key, then we can start the search on the current page
+ ** without needing to go back to root.
+ */
+ if( pCur->eState==CURSOR_VALID
+ && pCur->pPage->leaf
+ && cursorOnLastPage(pCur)
+ ){
+ int c;
+ if( pCur->ix==pCur->pPage->nCell-1
+ && (c = indexCellCompare(pCur, pCur->ix, pIdxKey, xRecordCompare))<=0
+ && pIdxKey->errCode==SQLITE_OK
+ ){
+ *pRes = c;
+ return SQLITE_OK; /* Cursor already pointing at the correct spot */
+ }
+ if( pCur->iPage>0
+ && indexCellCompare(pCur, 0, pIdxKey, xRecordCompare)<=0
+ && pIdxKey->errCode==SQLITE_OK
+ ){
+ pCur->curFlags &= ~BTCF_ValidOvfl;
+ if( !pCur->pPage->isInit ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+ goto bypass_moveto_root; /* Start search on the current page */
+ }
+ pIdxKey->errCode = SQLITE_OK;
+ }
+
+ rc = moveToRoot(pCur);
+ if( rc ){
+ if( rc==SQLITE_EMPTY ){
+ assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 );
+ *pRes = -1;
+ return SQLITE_OK;
+ }
+ return rc;
+ }
+
+bypass_moveto_root:
+ assert( pCur->pPage );
+ assert( pCur->pPage->isInit );
+ assert( pCur->eState==CURSOR_VALID );
+ assert( pCur->pPage->nCell > 0 );
+ assert( pCur->curIntKey==0 );
+ assert( pIdxKey!=0 );
+ for(;;){
+ int lwr, upr, idx, c;
+ Pgno chldPg;
+ MemPage *pPage = pCur->pPage;
+ 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
+ ** not run. If this is not the root-page, then the moveToChild() routine
+ ** would have already detected db corruption. Similarly, pPage must
+ ** be the right kind (index or table) of b-tree page. Otherwise
+ ** a moveToChild() or moveToRoot() call would have detected corruption. */
+ assert( pPage->nCell>0 );
+ assert( pPage->intKey==0 );
+ lwr = 0;
+ upr = pPage->nCell-1;
+ idx = upr>>1; /* idx = (lwr+upr)/2; */
+ for(;;){
+ int nCell; /* Size of the pCell cell in bytes */
+ pCell = findCellPastPtr(pPage, idx);
+
+ /* 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
+ ** varint. This information is used to attempt to avoid parsing
+ ** the entire cell by checking for the cases where the record is
+ ** stored entirely within the b-tree page by inspecting the first
+ ** 2 bytes of the cell.
+ */
+ 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 = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey);
+ }else if( !(pCell[1] & 0x80)
+ && (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal
+ ){
+ /* 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 = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey);
+ }else{
+ /* The record flows over onto one or more overflow pages. In
+ ** this case the whole cell needs to be parsed, a buffer allocated
+ ** and accessPayload() used to retrieve the record into the
+ ** buffer before VdbeRecordCompare() can be called.
+ **
+ ** If the record is corrupt, the xRecordCompare routine may read
+ ** up to two varints past the end of the buffer. An extra 18
+ ** bytes of padding is allocated at the end of the buffer in
+ ** case this happens. */
+ void *pCellKey;
+ u8 * const pCellBody = pCell - pPage->childPtrSize;
+ const int nOverrun = 18; /* Size of the overrun padding */
+ pPage->xParseCell(pPage, pCellBody, &pCur->info);
+ nCell = (int)pCur->info.nKey;
+ testcase( nCell<0 ); /* True if key size is 2^32 or more */
+ testcase( nCell==0 ); /* Invalid key size: 0x80 0x80 0x00 */
+ testcase( nCell==1 ); /* Invalid key size: 0x80 0x80 0x01 */
+ testcase( nCell==2 ); /* Minimum legal index key size */
+ if( nCell<2 || nCell/pCur->pBt->usableSize>pCur->pBt->nPage ){
+ rc = SQLITE_CORRUPT_PAGE(pPage);
+ goto moveto_index_finish;
+ }
+ pCellKey = sqlcipher_sqlite3Malloc( nCell+nOverrun );
+ if( pCellKey==0 ){
+ rc = SQLITE_NOMEM_BKPT;
+ goto moveto_index_finish;
}
- assert(
- (pIdxKey->errCode!=SQLITE_CORRUPT || c==0)
- && (pIdxKey->errCode!=SQLITE_NOMEM || pCur->pBtree->db->mallocFailed)
- );
- if( c<0 ){
- lwr = idx+1;
- }else if( c>0 ){
- upr = idx-1;
- }else{
- assert( c==0 );
- *pRes = 0;
- rc = SQLITE_OK;
- pCur->ix = (u16)idx;
- if( pIdxKey->errCode ) rc = SQLITE_CORRUPT_BKPT;
- goto moveto_finish;
+ pCur->ix = (u16)idx;
+ rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 0);
+ memset(((u8*)pCellKey)+nCell,0,nOverrun); /* Fix uninit warnings */
+ pCur->curFlags &= ~BTCF_ValidOvfl;
+ if( rc ){
+ sqlcipher_sqlite3_free(pCellKey);
+ goto moveto_index_finish;
}
- if( lwr>upr ) break;
- assert( lwr+upr>=0 );
- idx = (lwr+upr)>>1; /* idx = (lwr+upr)/2 */
+ c = sqlcipher_sqlite3VdbeRecordCompare(nCell, pCellKey, pIdxKey);
+ sqlcipher_sqlite3_free(pCellKey);
}
+ assert(
+ (pIdxKey->errCode!=SQLITE_CORRUPT || c==0)
+ && (pIdxKey->errCode!=SQLITE_NOMEM || pCur->pBtree->db->mallocFailed)
+ );
+ if( c<0 ){
+ lwr = idx+1;
+ }else if( c>0 ){
+ upr = idx-1;
+ }else{
+ assert( c==0 );
+ *pRes = 0;
+ rc = SQLITE_OK;
+ pCur->ix = (u16)idx;
+ if( pIdxKey->errCode ) rc = SQLITE_CORRUPT_BKPT;
+ goto moveto_index_finish;
+ }
+ if( lwr>upr ) break;
+ assert( lwr+upr>=0 );
+ idx = (lwr+upr)>>1; /* idx = (lwr+upr)/2 */
}
assert( lwr==upr+1 || (pPage->intKey && !pPage->leaf) );
assert( pPage->isInit );
if( pPage->leaf ){
- assert( pCur->ix<pCur->pPage->nCell );
+ assert( pCur->ix<pCur->pPage->nCell || CORRUPT_DB );
pCur->ix = (u16)idx;
*pRes = c;
rc = SQLITE_OK;
- goto moveto_finish;
+ goto moveto_index_finish;
}
-moveto_next_layer:
if( lwr>=pPage->nCell ){
chldPg = get4byte(&pPage->aData[pPage->hdrOffset+8]);
}else{
@@ -75035,7 +73160,7 @@ moveto_next_layer:
rc = moveToChild(pCur, chldPg);
if( rc ) break;
}
-moveto_finish:
+moveto_index_finish:
pCur->info.nSize = 0;
assert( (pCur->curFlags & BTCF_ValidOvfl)==0 );
return rc;
@@ -75136,16 +73261,6 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur){
return SQLITE_CORRUPT_BKPT;
}
- /* If the database file is corrupt, it is possible for the value of idx
- ** to be invalid here. This can only occur if a second cursor modifies
- ** the page while cursor pCur is holding a reference to it. Which can
- ** only happen if the database is corrupt in such a way as to link the
- ** page into more than one b-tree structure.
- **
- ** Update 2019-12-23: appears to long longer be possible after the
- ** addition of anotherValidCursor() condition on balance_deeper(). */
- harmless( idx>pPage->nCell );
-
if( idx>=pPage->nCell ){
if( !pPage->leaf ){
rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8]));
@@ -75506,7 +73621,7 @@ static int allocateBtreePage(
iPage = get4byte(&aData[8+closest*4]);
testcase( iPage==mxPage );
- if( iPage>mxPage ){
+ if( iPage>mxPage || iPage<2 ){
rc = SQLITE_CORRUPT_PGNO(iTrunk);
goto end_allocate_page;
}
@@ -75762,10 +73877,9 @@ static void freePage(MemPage *pPage, int *pRC){
}
/*
-** Free any overflow pages associated with the given Cell. Store
-** size information about the cell in pInfo.
+** Free the overflow pages associated with the given Cell.
*/
-static int clearCell(
+static SQLITE_NOINLINE int clearCellOverflow(
MemPage *pPage, /* The page that contains the Cell */
unsigned char *pCell, /* First byte of the Cell */
CellInfo *pInfo /* Size information about the cell */
@@ -75777,10 +73891,7 @@ static int clearCell(
u32 ovflPageSize;
assert( sqlcipher_sqlite3_mutex_held(pPage->pBt->mutex) );
- pPage->xParseCell(pPage, pCell, pInfo);
- if( pInfo->nLocal==pInfo->nPayload ){
- return SQLITE_OK; /* No overflow pages. Return without doing anything */
- }
+ assert( pInfo->nLocal!=pInfo->nPayload );
testcase( pCell + pInfo->nSize == pPage->aDataEnd );
testcase( pCell + (pInfo->nSize-1) == pPage->aDataEnd );
if( pCell + pInfo->nSize > pPage->aDataEnd ){
@@ -75836,6 +73947,21 @@ static int clearCell(
return SQLITE_OK;
}
+/* Call xParseCell to compute the size of a cell. If the cell contains
+** overflow, then invoke cellClearOverflow to clear out that overflow.
+** STore the result code (SQLITE_OK or some error code) in rc.
+**
+** Implemented as macro to force inlining for performance.
+*/
+#define BTREE_CLEAR_CELL(rc, pPage, pCell, sInfo) \
+ pPage->xParseCell(pPage, pCell, &sInfo); \
+ if( sInfo.nLocal!=sInfo.nPayload ){ \
+ rc = clearCellOverflow(pPage, pCell, &sInfo); \
+ }else{ \
+ rc = SQLITE_OK; \
+ }
+
+
/*
** Create the byte sequence used to represent a cell on page pPage
** and write that byte sequence into pCell[]. Overflow pages are
@@ -76046,16 +74172,24 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){
int hdr; /* Beginning of the header. 0 most pages. 100 page 1 */
if( *pRC ) return;
- assert( idx>=0 && idx<pPage->nCell );
+ assert( idx>=0 );
+ assert( idx<pPage->nCell );
assert( CORRUPT_DB || sz==cellSize(pPage, idx) );
assert( sqlcipher_sqlite3PagerIswriteable(pPage->pDbPage) );
assert( sqlcipher_sqlite3_mutex_held(pPage->pBt->mutex) );
assert( pPage->nFree>=0 );
data = pPage->aData;
ptr = &pPage->aCellIdx[2*idx];
+ assert( pPage->pBt->usableSize > (u32)(ptr-data) );
pc = get2byte(ptr);
hdr = pPage->hdrOffset;
- testcase( pc==get2byte(&data[hdr+5]) );
+#if 0 /* Not required. Omit for efficiency */
+ if( pc<hdr+pPage->nCell*2 ){
+ *pRC = SQLITE_CORRUPT_BKPT;
+ return;
+ }
+#endif
+ testcase( pc==(u32)get2byte(&data[hdr+5]) );
testcase( pc+sz==pPage->pBt->usableSize );
if( pc+sz > pPage->pBt->usableSize ){
*pRC = SQLITE_CORRUPT_BKPT;
@@ -76347,7 +74481,7 @@ static int rebuildPage(
assert( i<iEnd );
j = get2byte(&aData[hdr+5]);
- if( NEVER(j>(u32)usableSize) ){ j = 0; }
+ if( j>(u32)usableSize ){ j = 0; }
memcpy(&pTmp[j], &aData[j], usableSize - j);
for(k=0; pCArray->ixNx[k]<=i && ALWAYS(k<NB*2); k++){}
@@ -76358,7 +74492,7 @@ static int rebuildPage(
u8 *pCell = pCArray->apCell[i];
u16 sz = pCArray->szCell[i];
assert( sz>0 );
- if( SQLITE_WITHIN(pCell,aData,pEnd) ){
+ if( SQLITE_WITHIN(pCell,aData+j,pEnd) ){
if( ((uptr)(pCell+sz))>(uptr)pEnd ) return SQLITE_CORRUPT_BKPT;
pCell = &pTmp[pCell - aData];
}else if( (uptr)(pCell+sz)>(uptr)pSrcEnd
@@ -76371,9 +74505,8 @@ static int rebuildPage(
put2byte(pCellptr, (pData - aData));
pCellptr += 2;
if( pData < pCellptr ) return SQLITE_CORRUPT_BKPT;
- memcpy(pData, pCell, sz);
+ memmove(pData, pCell, sz);
assert( sz==pPg->xCellSize(pPg, pCell) || CORRUPT_DB );
- testcase( sz!=pPg->xCellSize(pPg,pCell) )
i++;
if( i>=iEnd ) break;
if( pCArray->ixNx[k]<=i ){
@@ -76512,7 +74645,9 @@ static int pageFreeArray(
}
pFree = pCell;
szFree = sz;
- if( pFree+sz>pEnd ) return 0;
+ if( pFree+sz>pEnd ){
+ return 0;
+ }
}else{
pFree = pCell;
szFree += sz;
@@ -76577,6 +74712,7 @@ static int editPage(
pData = &aData[get2byteNotZero(&aData[hdr+5])];
if( pData<pBegin ) goto editpage_fail;
+ if( pData>pPg->aDataEnd ) goto editpage_fail;
/* Add cells to the start of the page */
if( iNew<iOld ){
@@ -76936,13 +75072,10 @@ static int balance_nonroot(
Pgno pgno; /* Temp var to store a page number in */
u8 abDone[NB+2]; /* True after i'th new page is populated */
Pgno aPgno[NB+2]; /* Page numbers of new pages before shuffling */
- Pgno aPgOrder[NB+2]; /* Copy of aPgno[] used for sorting pages */
- u16 aPgFlags[NB+2]; /* flags field of new pages before shuffling */
- CellArray b; /* Parsed information on cells being balanced */
+ CellArray b; /* Parsed information on cells being balanced */
memset(abDone, 0, sizeof(abDone));
- b.nCell = 0;
- b.apCell = 0;
+ memset(&b, 0, sizeof(b));
pBt = pParent->pBt;
assert( sqlcipher_sqlite3_mutex_held(pBt->mutex) );
assert( sqlcipher_sqlite3PagerIswriteable(pParent->pDbPage) );
@@ -76993,7 +75126,9 @@ static int balance_nonroot(
}
pgno = get4byte(pRight);
while( 1 ){
- rc = getAndInitPage(pBt, pgno, &apOld[i], 0, 0);
+ if( rc==SQLITE_OK ){
+ rc = getAndInitPage(pBt, pgno, &apOld[i], 0, 0);
+ }
if( rc ){
memset(apOld, 0, (i+1)*sizeof(MemPage*));
goto balance_cleanup;
@@ -77005,6 +75140,7 @@ static int balance_nonroot(
goto balance_cleanup;
}
}
+ nMaxCells += apOld[i]->nCell + ArraySize(pParent->apOvfl);
if( (i--)==0 ) break;
if( pParent->nOverflow && i+nxDiv==pParent->aiOvfl[0] ){
@@ -77032,12 +75168,10 @@ static int balance_nonroot(
if( pBt->btsFlags & BTS_FAST_SECURE ){
int iOff;
+ /* If the following if() condition is not true, the db is corrupted.
+ ** The call to dropCell() below will detect this. */
iOff = SQLITE_PTR_TO_INT(apDiv[i]) - SQLITE_PTR_TO_INT(pParent->aData);
- if( (iOff+szNew[i])>(int)pBt->usableSize ){
- rc = SQLITE_CORRUPT_BKPT;
- memset(apOld, 0, (i+1)*sizeof(MemPage*));
- goto balance_cleanup;
- }else{
+ if( (iOff+szNew[i])<=(int)pBt->usableSize ){
memcpy(&aOvflSpace[iOff], apDiv[i], szNew[i]);
apDiv[i] = &aOvflSpace[apDiv[i]-pParent->aData];
}
@@ -77048,7 +75182,6 @@ static int balance_nonroot(
/* Make nMaxCells a multiple of 4 in order to preserve 8-byte
** alignment */
- nMaxCells = nOld*(MX_CELL(pBt) + ArraySize(pParent->apOvfl));
nMaxCells = (nMaxCells + 3)&~3;
/*
@@ -77165,7 +75298,7 @@ static int balance_nonroot(
b.szCell[b.nCell] = b.szCell[b.nCell] - leafCorrection;
if( !pOld->leaf ){
assert( leafCorrection==0 );
- assert( pOld->hdrOffset==0 );
+ assert( pOld->hdrOffset==0 || CORRUPT_DB );
/* The right pointer of the child page pOld becomes the left
** pointer of the divider cell */
memcpy(b.apCell[b.nCell], &pOld->aData[8], 4);
@@ -77331,6 +75464,11 @@ static int balance_nonroot(
apOld[i] = 0;
rc = sqlcipher_sqlite3PagerWrite(pNew->pDbPage);
nNew++;
+ if( sqlcipher_sqlite3PagerPageRefcount(pNew->pDbPage)!=1+(i==(iParentIdx-nxDiv))
+ && rc==SQLITE_OK
+ ){
+ rc = SQLITE_CORRUPT_BKPT;
+ }
if( rc ) goto balance_cleanup;
}else{
assert( i>0 );
@@ -77357,42 +75495,39 @@ static int balance_nonroot(
** of the table is closer to a linear scan through the file. That in turn
** helps the operating system to deliver pages from the disk more rapidly.
**
- ** An O(n^2) insertion sort algorithm is used, but since n is never more
- ** than (NB+2) (a small constant), that should not be a problem.
+ ** An O(N*N) sort algorithm is used, but since N is never more than NB+2
+ ** (5), that is not a performance concern.
**
** When NB==3, this one optimization makes the database about 25% faster
** for large insertions and deletions.
*/
for(i=0; i<nNew; i++){
- aPgOrder[i] = aPgno[i] = apNew[i]->pgno;
- aPgFlags[i] = apNew[i]->pDbPage->flags;
- for(j=0; j<i; j++){
- if( aPgno[j]==aPgno[i] ){
- /* This branch is taken if the set of sibling pages somehow contains
- ** duplicate entries. This can happen if the database is corrupt.
- ** It would be simpler to detect this as part of the loop below, but
- ** we do the detection here in order to avoid populating the pager
- ** cache with two separate objects associated with the same
- ** page number. */
- assert( CORRUPT_DB );
- rc = SQLITE_CORRUPT_BKPT;
- goto balance_cleanup;
- }
- }
+ aPgno[i] = apNew[i]->pgno;
+ assert( apNew[i]->pDbPage->flags & PGHDR_WRITEABLE );
+ assert( apNew[i]->pDbPage->flags & PGHDR_DIRTY );
}
- for(i=0; i<nNew; i++){
- int iBest = 0; /* aPgno[] index of page number to use */
- for(j=1; j<nNew; j++){
- if( aPgOrder[j]<aPgOrder[iBest] ) iBest = j;
+ for(i=0; i<nNew-1; i++){
+ int iB = i;
+ for(j=i+1; j<nNew; j++){
+ if( apNew[j]->pgno < apNew[iB]->pgno ) iB = j;
}
- pgno = aPgOrder[iBest];
- aPgOrder[iBest] = 0xffffffff;
- if( iBest!=i ){
- if( iBest>i ){
- sqlcipher_sqlite3PagerRekey(apNew[iBest]->pDbPage, pBt->nPage+iBest+1, 0);
- }
- sqlcipher_sqlite3PagerRekey(apNew[i]->pDbPage, pgno, aPgFlags[iBest]);
- apNew[i]->pgno = pgno;
+
+ /* If apNew[i] has a page number that is bigger than any of the
+ ** subsequence apNew[i] entries, then swap apNew[i] with the subsequent
+ ** entry that has the smallest page number (which we know to be
+ ** entry apNew[iB]).
+ */
+ if( iB!=i ){
+ Pgno pgnoA = apNew[i]->pgno;
+ Pgno pgnoB = apNew[iB]->pgno;
+ Pgno pgnoTemp = (PENDING_BYTE/pBt->pageSize)+1;
+ u16 fgA = apNew[i]->pDbPage->flags;
+ u16 fgB = apNew[iB]->pDbPage->flags;
+ sqlcipher_sqlite3PagerRekey(apNew[i]->pDbPage, pgnoTemp, fgB);
+ sqlcipher_sqlite3PagerRekey(apNew[iB]->pDbPage, pgnoA, fgA);
+ sqlcipher_sqlite3PagerRekey(apNew[i]->pDbPage, pgnoB, fgB);
+ apNew[i]->pgno = pgnoB;
+ apNew[iB]->pgno = pgnoA;
}
}
@@ -77485,6 +75620,7 @@ static int balance_nonroot(
u8 *pCell;
u8 *pTemp;
int sz;
+ u8 *pSrcEnd;
MemPage *pNew = apNew[i];
j = cntNew[i];
@@ -77528,6 +75664,12 @@ static int balance_nonroot(
iOvflSpace += sz;
assert( sz<=pBt->maxLocal+23 );
assert( iOvflSpace <= (int)pBt->pageSize );
+ for(k=0; b.ixNx[k]<=j && ALWAYS(k<NB*2); k++){}
+ pSrcEnd = b.apEnd[k];
+ if( SQLITE_WITHIN(pSrcEnd, pCell, pCell+sz) ){
+ rc = SQLITE_CORRUPT_BKPT;
+ goto balance_cleanup;
+ }
insertCell(pParent, nxDiv+i, pCell, sz, pTemp, pNew->pgno, &rc);
if( rc!=SQLITE_OK ) goto balance_cleanup;
assert( sqlcipher_sqlite3PagerIswriteable(pParent->pDbPage) );
@@ -77741,7 +75883,7 @@ static int balance_deeper(MemPage *pRoot, MemPage **ppChild){
** Return SQLITE_CORRUPT if any cursor other than pCur is currently valid
** on the same B-tree as pCur.
**
-** This can if a database is corrupt with two or more SQL tables
+** This can occur if a database is corrupt with two or more SQL tables
** pointing to the same b-tree. If an insert occurs on one SQL table
** and causes a BEFORE TRIGGER to do a secondary insert on the other SQL
** table linked to the same b-tree. If the secondary insert causes a
@@ -77773,7 +75915,6 @@ static int anotherValidCursor(BtCursor *pCur){
*/
static int balance(BtCursor *pCur){
int rc = SQLITE_OK;
- const int nMin = pCur->pBt->usableSize * 2 / 3;
u8 aBalanceQuickSpace[13];
u8 *pFree = 0;
@@ -77785,7 +75926,11 @@ static int balance(BtCursor *pCur){
MemPage *pPage = pCur->pPage;
if( NEVER(pPage->nFree<0) && btreeComputeFreeSpace(pPage) ) break;
- if( pPage->nOverflow==0 && pPage->nFree<=nMin ){
+ if( pPage->nOverflow==0 && pPage->nFree*3<=(int)pCur->pBt->usableSize*2 ){
+ /* No rebalance required as long as:
+ ** (1) There are no overflow cells
+ ** (2) The amount of free space on the page is less than 2/3rds of
+ ** the total usable space on the page. */
break;
}else if( (iPage = pCur->iPage)==0 ){
if( pPage->nOverflow && (rc = anotherValidCursor(pCur))==SQLITE_OK ){
@@ -77970,7 +76115,7 @@ static int btreeOverwriteCell(BtCursor *pCur, const BtreePayload *pX){
do{
rc = btreeGetPage(pBt, ovflPgno, &pPage, 0);
if( rc ) return rc;
- if( sqlcipher_sqlite3PagerPageRefcount(pPage->pDbPage)!=1 ){
+ if( sqlcipher_sqlite3PagerPageRefcount(pPage->pDbPage)!=1 || pPage->isInit ){
rc = SQLITE_CORRUPT_BKPT;
}else{
if( iOffset+ovflPageSize<(u32)nTotal ){
@@ -78005,7 +76150,7 @@ static int btreeOverwriteCell(BtCursor *pCur, const BtreePayload *pX){
** pX.pData,nData,nZero fields must be zero.
**
** If the seekResult parameter is non-zero, then a successful call to
-** MovetoUnpacked() to seek cursor pCur to (pKey,nKey) has already
+** sqlcipher_sqlite3BtreeIndexMoveto() to seek cursor pCur to (pKey,nKey) has already
** been performed. In other words, if seekResult!=0 then the cursor
** is currently pointing to a cell that will be adjacent to the cell
** to be inserted. If seekResult<0 then pCur points to a cell that is
@@ -78023,7 +76168,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3BtreeInsert(
BtCursor *pCur, /* Insert data into the table of this cursor */
const BtreePayload *pX, /* Content of the row to be inserted */
int flags, /* True if this is likely an append */
- int seekResult /* Result of prior MovetoUnpacked() call */
+ int seekResult /* Result of prior IndexMoveto() call */
){
int rc;
int loc = seekResult; /* -1: before desired location +1: after */
@@ -78035,25 +76180,8 @@ SQLITE_PRIVATE int sqlcipher_sqlite3BtreeInsert(
unsigned char *oldCell;
unsigned char *newCell = 0;
- assert( (flags & (BTREE_SAVEPOSITION|BTREE_APPEND))==flags );
-
- if( pCur->eState==CURSOR_FAULT ){
- assert( pCur->skipNext!=SQLITE_OK );
- return pCur->skipNext;
- }
-
- assert( cursorOwnsBtShared(pCur) );
- 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) );
-
- /* Assert that the caller has been consistent. If this cursor was opened
- ** expecting an index b-tree, then the caller should be inserting blob
- ** keys with no associated data. If the cursor was opened expecting an
- ** intkey table, the caller should be inserting integer keys with a
- ** blob of associated data. */
- assert( (pX->pKey==0)==(pCur->pKeyInfo==0) );
+ assert( (flags & (BTREE_SAVEPOSITION|BTREE_APPEND|BTREE_PREFORMAT))==flags );
+ assert( (flags & BTREE_PREFORMAT)==0 || seekResult || pCur->pKeyInfo==0 );
/* Save the positions of any other cursors open on this table.
**
@@ -78069,13 +76197,46 @@ SQLITE_PRIVATE int sqlcipher_sqlite3BtreeInsert(
if( pCur->curFlags & BTCF_Multiple ){
rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur);
if( rc ) return rc;
+ if( loc && pCur->iPage<0 ){
+ /* This can only happen if the schema is corrupt such that there is more
+ ** than one table or index with the same root page as used by the cursor.
+ ** Which can only happen if the SQLITE_NoSchemaError flag was set when
+ ** the schema was loaded. This cannot be asserted though, as a user might
+ ** set the flag, load the schema, and then unset the flag. */
+ return SQLITE_CORRUPT_BKPT;
+ }
+ }
+
+ /* Ensure that the cursor is not in the CURSOR_FAULT state and that it
+ ** points to a valid cell.
+ */
+ if( pCur->eState>=CURSOR_REQUIRESEEK ){
+ testcase( pCur->eState==CURSOR_REQUIRESEEK );
+ testcase( pCur->eState==CURSOR_FAULT );
+ rc = moveToRoot(pCur);
+ if( rc && rc!=SQLITE_EMPTY ) return rc;
}
+ assert( cursorOwnsBtShared(pCur) );
+ 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) );
+
+ /* Assert that the caller has been consistent. If this cursor was opened
+ ** expecting an index b-tree, then the caller should be inserting blob
+ ** keys with no associated data. If the cursor was opened expecting an
+ ** intkey table, the caller should be inserting integer keys with a
+ ** blob of associated data. */
+ assert( (flags & BTREE_PREFORMAT) || (pX->pKey==0)==(pCur->pKeyInfo==0) );
+
if( pCur->pKeyInfo==0 ){
assert( pX->pKey==0 );
/* If this is an insert into a table b-tree, invalidate any incrblob
** cursors open on the row being replaced */
- invalidateIncrblobCursors(p, pCur->pgnoRoot, pX->nKey, 0);
+ if( p->hasIncrblobCur ){
+ invalidateIncrblobCursors(p, pCur->pgnoRoot, pX->nKey, 0);
+ }
/* If BTREE_SAVEPOSITION is set, the cursor must already be pointing
** to a row with the same key as the new entry being inserted.
@@ -78108,7 +76269,8 @@ SQLITE_PRIVATE int sqlcipher_sqlite3BtreeInsert(
** to an adjacent cell. Move the cursor so that it is pointing either
** to the cell to be overwritten or an adjacent cell.
*/
- rc = sqlcipher_sqlite3BtreeMovetoUnpacked(pCur, 0, pX->nKey, flags!=0, &loc);
+ rc = sqlcipher_sqlite3BtreeTableMoveto(pCur, pX->nKey,
+ (flags & BTREE_APPEND)!=0, &loc);
if( rc ) return rc;
}
}else{
@@ -78131,13 +76293,11 @@ SQLITE_PRIVATE int sqlcipher_sqlite3BtreeInsert(
r.aMem = pX->aMem;
r.nField = pX->nMem;
r.default_rc = 0;
- r.errCode = 0;
- r.r1 = 0;
- r.r2 = 0;
r.eqSeen = 0;
- rc = sqlcipher_sqlite3BtreeMovetoUnpacked(pCur, &r, 0, flags!=0, &loc);
+ rc = sqlcipher_sqlite3BtreeIndexMoveto(pCur, &r, &loc);
}else{
- rc = btreeMoveto(pCur, pX->pKey, pX->nKey, flags!=0, &loc);
+ rc = btreeMoveto(pCur, pX->pKey, pX->nKey,
+ (flags & BTREE_APPEND)!=0, &loc);
}
if( rc ) return rc;
}
@@ -78156,17 +76316,16 @@ SQLITE_PRIVATE int sqlcipher_sqlite3BtreeInsert(
return btreeOverwriteCell(pCur, &x2);
}
}
-
}
assert( pCur->eState==CURSOR_VALID
- || (pCur->eState==CURSOR_INVALID && loc)
- || CORRUPT_DB );
+ || (pCur->eState==CURSOR_INVALID && loc) );
pPage = pCur->pPage;
- assert( pPage->intKey || pX->nKey>=0 );
+ assert( pPage->intKey || pX->nKey>=0 || (flags & BTREE_PREFORMAT) );
assert( pPage->leaf || !pPage->intKey );
if( pPage->nFree<0 ){
- if( pCur->eState>CURSOR_INVALID ){
+ if( NEVER(pCur->eState>CURSOR_INVALID) ){
+ /* ^^^^^--- due to the moveToRoot() call above */
rc = SQLITE_CORRUPT_BKPT;
}else{
rc = btreeComputeFreeSpace(pPage);
@@ -78177,17 +76336,34 @@ SQLITE_PRIVATE int sqlcipher_sqlite3BtreeInsert(
TRACE(("INSERT: table=%d nkey=%lld ndata=%d page=%d %s\n",
pCur->pgnoRoot, pX->nKey, pX->nData, pPage->pgno,
loc==0 ? "overwrite" : "new entry"));
- assert( pPage->isInit );
+ assert( pPage->isInit || CORRUPT_DB );
newCell = pBt->pTmpSpace;
assert( newCell!=0 );
- rc = fillInCell(pPage, newCell, pX, &szNew);
+ if( flags & BTREE_PREFORMAT ){
+ rc = SQLITE_OK;
+ szNew = pBt->nPreformatSize;
+ if( szNew<4 ) szNew = 4;
+ if( ISAUTOVACUUM && szNew>pPage->maxLocal ){
+ CellInfo info;
+ pPage->xParseCell(pPage, newCell, &info);
+ if( info.nPayload!=info.nLocal ){
+ Pgno ovfl = get4byte(&newCell[szNew-4]);
+ ptrmapPut(pBt, ovfl, PTRMAP_OVERFLOW1, pPage->pgno, &rc);
+ }
+ }
+ }else{
+ rc = fillInCell(pPage, newCell, pX, &szNew);
+ }
if( rc ) goto end_insert;
assert( szNew==pPage->xCellSize(pPage, newCell) );
assert( szNew <= MX_CELL_SIZE(pBt) );
idx = pCur->ix;
if( loc==0 ){
CellInfo info;
- assert( idx<pPage->nCell );
+ assert( idx>=0 );
+ if( idx>=pPage->nCell ){
+ return SQLITE_CORRUPT_BKPT;
+ }
rc = sqlcipher_sqlite3PagerWrite(pPage->pDbPage);
if( rc ){
goto end_insert;
@@ -78196,7 +76372,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3BtreeInsert(
if( !pPage->leaf ){
memcpy(newCell, oldCell, 4);
}
- rc = clearCell(pPage, oldCell, &info);
+ BTREE_CLEAR_CELL(rc, pPage, oldCell, info);
testcase( pCur->curFlags & BTCF_ValidOvfl );
invalidateOverflowCache(pCur);
if( info.nSize==szNew && info.nLocal==info.nPayload
@@ -78288,6 +76464,118 @@ end_insert:
}
/*
+** This function is used as part of copying the current row from cursor
+** pSrc into cursor pDest. If the cursors are open on intkey tables, then
+** parameter iKey is used as the rowid value when the record is copied
+** into pDest. Otherwise, the record is copied verbatim.
+**
+** This function does not actually write the new value to cursor pDest.
+** Instead, it creates and populates any required overflow pages and
+** writes the data for the new cell into the BtShared.pTmpSpace buffer
+** for the destination database. The size of the cell, in bytes, is left
+** in BtShared.nPreformatSize. The caller completes the insertion by
+** calling sqlcipher_sqlite3BtreeInsert() with the BTREE_PREFORMAT flag specified.
+**
+** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
+*/
+SQLITE_PRIVATE int sqlcipher_sqlite3BtreeTransferRow(BtCursor *pDest, BtCursor *pSrc, i64 iKey){
+ int rc = SQLITE_OK;
+ BtShared *pBt = pDest->pBt;
+ u8 *aOut = pBt->pTmpSpace; /* Pointer to next output buffer */
+ const u8 *aIn; /* Pointer to next input buffer */
+ u32 nIn; /* Size of input buffer aIn[] */
+ u32 nRem; /* Bytes of data still to copy */
+
+ getCellInfo(pSrc);
+ if( pSrc->info.nPayload<0x80 ){
+ *(aOut++) = pSrc->info.nPayload;
+ }else{
+ aOut += sqlcipher_sqlite3PutVarint(aOut, pSrc->info.nPayload);
+ }
+ if( pDest->pKeyInfo==0 ) aOut += putVarint(aOut, iKey);
+ nIn = pSrc->info.nLocal;
+ aIn = pSrc->info.pPayload;
+ if( aIn+nIn>pSrc->pPage->aDataEnd ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+ nRem = pSrc->info.nPayload;
+ if( nIn==nRem && nIn<pDest->pPage->maxLocal ){
+ memcpy(aOut, aIn, nIn);
+ pBt->nPreformatSize = nIn + (aOut - pBt->pTmpSpace);
+ }else{
+ Pager *pSrcPager = pSrc->pBt->pPager;
+ u8 *pPgnoOut = 0;
+ Pgno ovflIn = 0;
+ DbPage *pPageIn = 0;
+ MemPage *pPageOut = 0;
+ u32 nOut; /* Size of output buffer aOut[] */
+
+ nOut = btreePayloadToLocal(pDest->pPage, pSrc->info.nPayload);
+ pBt->nPreformatSize = nOut + (aOut - pBt->pTmpSpace);
+ if( nOut<pSrc->info.nPayload ){
+ pPgnoOut = &aOut[nOut];
+ pBt->nPreformatSize += 4;
+ }
+
+ if( nRem>nIn ){
+ if( aIn+nIn+4>pSrc->pPage->aDataEnd ){
+ return SQLITE_CORRUPT_BKPT;
+ }
+ ovflIn = get4byte(&pSrc->info.pPayload[nIn]);
+ }
+
+ do {
+ nRem -= nOut;
+ do{
+ assert( nOut>0 );
+ if( nIn>0 ){
+ int nCopy = MIN(nOut, nIn);
+ memcpy(aOut, aIn, nCopy);
+ nOut -= nCopy;
+ nIn -= nCopy;
+ aOut += nCopy;
+ aIn += nCopy;
+ }
+ if( nOut>0 ){
+ sqlcipher_sqlite3PagerUnref(pPageIn);
+ pPageIn = 0;
+ rc = sqlcipher_sqlite3PagerGet(pSrcPager, ovflIn, &pPageIn, PAGER_GET_READONLY);
+ if( rc==SQLITE_OK ){
+ aIn = (const u8*)sqlcipher_sqlite3PagerGetData(pPageIn);
+ ovflIn = get4byte(aIn);
+ aIn += 4;
+ nIn = pSrc->pBt->usableSize - 4;
+ }
+ }
+ }while( rc==SQLITE_OK && nOut>0 );
+
+ if( rc==SQLITE_OK && nRem>0 && ALWAYS(pPgnoOut) ){
+ Pgno pgnoNew;
+ MemPage *pNew = 0;
+ rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0);
+ put4byte(pPgnoOut, pgnoNew);
+ if( ISAUTOVACUUM && pPageOut ){
+ ptrmapPut(pBt, pgnoNew, PTRMAP_OVERFLOW2, pPageOut->pgno, &rc);
+ }
+ releasePage(pPageOut);
+ pPageOut = pNew;
+ if( pPageOut ){
+ pPgnoOut = pPageOut->aData;
+ put4byte(pPgnoOut, 0);
+ aOut = &pPgnoOut[4];
+ nOut = MIN(pBt->usableSize - 4, nRem);
+ }
+ }
+ }while( nRem>0 && rc==SQLITE_OK );
+
+ releasePage(pPageOut);
+ sqlcipher_sqlite3PagerUnref(pPageIn);
+ }
+
+ return rc;
+}
+
+/*
** Delete the entry that the cursor is pointing to.
**
** If the BTREE_SAVEPOSITION bit of the flags parameter is zero, then
@@ -78307,14 +76595,13 @@ end_insert:
SQLITE_PRIVATE int sqlcipher_sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
Btree *p = pCur->pBtree;
BtShared *pBt = p->pBt;
- int rc; /* Return code */
- MemPage *pPage; /* Page to delete cell from */
- unsigned char *pCell; /* Pointer to cell to delete */
- int iCellIdx; /* Index of cell to delete */
- int iCellDepth; /* Depth of node containing pCell */
- CellInfo info; /* Size of the cell being deleted */
- int bSkipnext = 0; /* Leaf cursor in SKIPNEXT state */
- u8 bPreserve = flags & BTREE_SAVEPOSITION; /* Keep cursor valid */
+ int rc; /* Return code */
+ MemPage *pPage; /* Page to delete cell from */
+ unsigned char *pCell; /* Pointer to cell to delete */
+ int iCellIdx; /* Index of cell to delete */
+ int iCellDepth; /* Depth of node containing pCell */
+ CellInfo info; /* Size of the cell being deleted */
+ u8 bPreserve; /* Keep cursor valid. 2 for CURSOR_SKIPNEXT */
assert( cursorOwnsBtShared(pCur) );
assert( pBt->inTransaction==TRANS_WRITE );
@@ -78323,30 +76610,49 @@ SQLITE_PRIVATE int sqlcipher_sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
assert( !hasReadConflicts(p, pCur->pgnoRoot) );
assert( (flags & ~(BTREE_SAVEPOSITION | BTREE_AUXDELETE))==0 );
- if( pCur->eState==CURSOR_REQUIRESEEK ){
- rc = btreeRestoreCursorPosition(pCur);
- if( rc ) return rc;
+ if( pCur->eState!=CURSOR_VALID ){
+ if( pCur->eState>=CURSOR_REQUIRESEEK ){
+ rc = btreeRestoreCursorPosition(pCur);
+ assert( rc!=SQLITE_OK || CORRUPT_DB || pCur->eState==CURSOR_VALID );
+ if( rc || pCur->eState!=CURSOR_VALID ) return rc;
+ }else{
+ return SQLITE_CORRUPT_BKPT;
+ }
}
assert( pCur->eState==CURSOR_VALID );
iCellDepth = pCur->iPage;
iCellIdx = pCur->ix;
pPage = pCur->pPage;
+ if( pPage->nCell<=iCellIdx ){
+ return SQLITE_CORRUPT_BKPT;
+ }
pCell = findCell(pPage, iCellIdx);
- if( pPage->nFree<0 && btreeComputeFreeSpace(pPage) ) return SQLITE_CORRUPT;
+ if( pPage->nFree<0 && btreeComputeFreeSpace(pPage) ){
+ return SQLITE_CORRUPT_BKPT;
+ }
- /* If the bPreserve flag is set to true, then the cursor position must
+ /* If the BTREE_SAVEPOSITION bit is on, then the cursor position must
** be preserved following this delete operation. If the current delete
** will cause a b-tree rebalance, then this is done by saving the cursor
** key and leaving the cursor in CURSOR_REQUIRESEEK state before
** returning.
**
- ** Or, if the current delete will not cause a rebalance, then the cursor
+ ** If the current delete will not cause a rebalance, then the cursor
** will be left in CURSOR_SKIPNEXT state pointing to the entry immediately
- ** before or after the deleted entry. In this case set bSkipnext to true. */
+ ** before or after the deleted entry.
+ **
+ ** The bPreserve value records which path is required:
+ **
+ ** bPreserve==0 Not necessary to save the cursor position
+ ** bPreserve==1 Use CURSOR_REQUIRESEEK to save the cursor position
+ ** bPreserve==2 Cursor won't move. Set CURSOR_SKIPNEXT.
+ */
+ bPreserve = (flags & BTREE_SAVEPOSITION)!=0;
if( bPreserve ){
if( !pPage->leaf
- || (pPage->nFree+cellSizePtr(pPage,pCell)+2)>(int)(pBt->usableSize*2/3)
+ || (pPage->nFree+pPage->xCellSize(pPage,pCell)+2) >
+ (int)(pBt->usableSize*2/3)
|| pPage->nCell==1 /* See dbfuzz001.test for a test case */
){
/* A b-tree rebalance will be required after deleting this entry.
@@ -78354,7 +76660,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
rc = saveCursorKey(pCur);
if( rc ) return rc;
}else{
- bSkipnext = 1;
+ bPreserve = 2;
}
}
@@ -78380,7 +76686,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
/* If this is a delete operation to remove a row from a table b-tree,
** invalidate any incrblob cursors open on the row being deleted. */
- if( pCur->pKeyInfo==0 ){
+ if( pCur->pKeyInfo==0 && p->hasIncrblobCur ){
invalidateIncrblobCursors(p, pCur->pgnoRoot, pCur->info.nKey, 0);
}
@@ -78389,7 +76695,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
** itself from within the page. */
rc = sqlcipher_sqlite3PagerWrite(pPage->pDbPage);
if( rc ) return rc;
- rc = clearCell(pPage, pCell, &info);
+ BTREE_CLEAR_CELL(rc, pPage, pCell, info);
dropCell(pPage, iCellIdx, info.nSize, &rc);
if( rc ) return rc;
@@ -78442,7 +76748,15 @@ SQLITE_PRIVATE int sqlcipher_sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
** been corrected, so be it. Otherwise, after balancing the leaf node,
** walk the cursor up the tree to the internal node and balance it as
** well. */
- rc = balance(pCur);
+ assert( pCur->pPage->nOverflow==0 );
+ assert( pCur->pPage->nFree>=0 );
+ if( pCur->pPage->nFree*3<=(int)pCur->pBt->usableSize*2 ){
+ /* Optimization: If the free space is less than 2/3rds of the page,
+ ** then balance() will always be a no-op. No need to invoke it. */
+ rc = SQLITE_OK;
+ }else{
+ rc = balance(pCur);
+ }
if( rc==SQLITE_OK && pCur->iPage>iCellDepth ){
releasePageNotNull(pCur->pPage);
pCur->iPage--;
@@ -78454,8 +76768,8 @@ SQLITE_PRIVATE int sqlcipher_sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
}
if( rc==SQLITE_OK ){
- if( bSkipnext ){
- assert( bPreserve && (pCur->iPage==iCellDepth || CORRUPT_DB) );
+ if( bPreserve>1 ){
+ assert( (pCur->iPage==iCellDepth || CORRUPT_DB) );
assert( pPage==pCur->pPage || CORRUPT_DB );
assert( (pPage->nCell>0 || CORRUPT_DB) && iCellIdx<=pPage->nCell );
pCur->eState = CURSOR_SKIPNEXT;
@@ -78649,7 +76963,7 @@ static int clearDatabasePage(
BtShared *pBt, /* The BTree that contains the table */
Pgno pgno, /* Page number to clear */
int freePageFlag, /* Deallocate page if true */
- int *pnChange /* Add number of Cells freed to this counter */
+ i64 *pnChange /* Add number of Cells freed to this counter */
){
MemPage *pPage;
int rc;
@@ -78664,11 +76978,12 @@ static int clearDatabasePage(
}
rc = getAndInitPage(pBt, pgno, &pPage, 0, 0);
if( rc ) return rc;
- if( pPage->bBusy ){
+ if( (pBt->openFlags & BTREE_SINGLE)==0
+ && sqlcipher_sqlite3PagerPageRefcount(pPage->pDbPage) != (1 + (pgno==1))
+ ){
rc = SQLITE_CORRUPT_BKPT;
goto cleardatabasepage_out;
}
- pPage->bBusy = 1;
hdr = pPage->hdrOffset;
for(i=0; i<pPage->nCell; i++){
pCell = findCell(pPage, i);
@@ -78676,14 +76991,15 @@ static int clearDatabasePage(
rc = clearDatabasePage(pBt, get4byte(pCell), 1, pnChange);
if( rc ) goto cleardatabasepage_out;
}
- rc = clearCell(pPage, pCell, &info);
+ BTREE_CLEAR_CELL(rc, pPage, pCell, info);
if( rc ) goto cleardatabasepage_out;
}
if( !pPage->leaf ){
rc = clearDatabasePage(pBt, get4byte(&pPage->aData[hdr+8]), 1, pnChange);
if( rc ) goto cleardatabasepage_out;
- }else if( pnChange ){
- assert( pPage->intKey || CORRUPT_DB );
+ if( pPage->intKey ) pnChange = 0;
+ }
+ if( pnChange ){
testcase( !pPage->intKey );
*pnChange += pPage->nCell;
}
@@ -78694,7 +77010,6 @@ static int clearDatabasePage(
}
cleardatabasepage_out:
- pPage->bBusy = 0;
releasePage(pPage);
return rc;
}
@@ -78708,11 +77023,10 @@ cleardatabasepage_out:
** read cursors on the table. Open write cursors are moved to the
** root of the table.
**
-** If pnChange is not NULL, then table iTable must be an intkey table. The
-** integer value pointed to by pnChange is incremented by the number of
-** entries in the table.
+** If pnChange is not NULL, then the integer value pointed to by pnChange
+** is incremented by the number of entries in the table.
*/
-SQLITE_PRIVATE int sqlcipher_sqlite3BtreeClearTable(Btree *p, int iTable, int *pnChange){
+SQLITE_PRIVATE int sqlcipher_sqlite3BtreeClearTable(Btree *p, int iTable, i64 *pnChange){
int rc;
BtShared *pBt = p->pBt;
sqlcipher_sqlite3BtreeEnter(p);
@@ -78724,7 +77038,9 @@ SQLITE_PRIVATE int sqlcipher_sqlite3BtreeClearTable(Btree *p, int iTable, int *p
/* Invalidate all incrblob cursors open on table iTable (assuming iTable
** is the root of a table b-tree - if it is not, the following call is
** a no-op). */
- invalidateIncrblobCursors(p, (Pgno)iTable, 0, 1);
+ if( p->hasIncrblobCur ){
+ invalidateIncrblobCursors(p, (Pgno)iTable, 0, 1);
+ }
rc = clearDatabasePage(pBt, (Pgno)iTable, 0, pnChange);
}
sqlcipher_sqlite3BtreeLeave(p);
@@ -78772,10 +77088,10 @@ static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
return SQLITE_CORRUPT_BKPT;
}
- rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0);
- if( rc ) return rc;
rc = sqlcipher_sqlite3BtreeClearTable(p, iTable, 0);
- if( rc ){
+ if( rc ) return rc;
+ rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0);
+ if( NEVER(rc) ){
releasePage(pPage);
return rc;
}
@@ -78884,7 +77200,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta)
assert( idx>=0 && idx<=15 );
if( idx==BTREE_DATA_VERSION ){
- *pMeta = sqlcipher_sqlite3PagerDataVersion(pBt->pPager) + p->iDataVersion;
+ *pMeta = sqlcipher_sqlite3PagerDataVersion(pBt->pPager) + p->iBDataVersion;
}else{
*pMeta = get4byte(&pBt->pPage1->aData[36 + idx*4]);
}
@@ -80043,14 +78359,13 @@ static Btree *findBtree(sqlcipher_sqlite3 *pErrorDb, sqlcipher_sqlite3 *pDb, con
if( i==1 ){
Parse sParse;
int rc = 0;
- memset(&sParse, 0, sizeof(sParse));
- sParse.db = pDb;
+ sqlcipher_sqlite3ParseObjectInit(&sParse,pDb);
if( sqlcipher_sqlite3OpenTempDatabase(&sParse) ){
sqlcipher_sqlite3ErrorWithMsg(pErrorDb, sParse.rc, "%s", sParse.zErrMsg);
rc = SQLITE_ERROR;
}
sqlcipher_sqlite3DbFree(pErrorDb, sParse.zErrMsg);
- sqlcipher_sqlite3ParserReset(&sParse);
+ sqlcipher_sqlite3ParseObjectReset(&sParse);
if( rc ){
return 0;
}
@@ -80115,12 +78430,12 @@ SQLITE_API sqlcipher_sqlite3_backup *sqlcipher_sqlite3_backup_init(
#ifdef SQLITE_HAS_CODEC
{
extern int sqlcipher_find_db_index(sqlcipher_sqlite3*, const char*);
- extern void sqlcipher_sqlite3CodecGetKey(sqlcipher_sqlite3*, int, void**, int*);
+ extern void sqlcipherCodecGetKey(sqlcipher_sqlite3*, int, void**, int*);
int srcNKey, destNKey;
void *zKey;
- sqlcipher_sqlite3CodecGetKey(pSrcDb, sqlcipher_find_db_index(pSrcDb, zSrcDb), &zKey, &srcNKey);
- sqlcipher_sqlite3CodecGetKey(pDestDb, sqlcipher_find_db_index(pDestDb, zDestDb), &zKey, &destNKey);
+ sqlcipherCodecGetKey(pSrcDb, sqlcipher_find_db_index(pSrcDb, zSrcDb), &zKey, &srcNKey);
+ sqlcipherCodecGetKey(pDestDb, sqlcipher_find_db_index(pDestDb, zDestDb), &zKey, &destNKey);
zKey = NULL;
/* either both databases must be plaintext, or both must be encrypted */
@@ -80216,6 +78531,7 @@ static int backupOnePage(
const i64 iEnd = (i64)iSrcPg*(i64)nSrcPgsz;
/* BEGIN SQLCIPHER */
#ifdef SQLITE_HAS_CODEC
+ extern void *sqlcipherPagerGetCodec(Pager*);
/* Use BtreeGetReserveNoMutex() for the source b-tree, as although it is
** guaranteed that the shared-mutex is held by this thread, handle
** p->pSrc may not actually be the owner. */
@@ -80244,7 +78560,7 @@ static int backupOnePage(
/* Backup is not possible if the page size of the destination is changing
** and a codec is in use.
*/
- if( nSrcPgsz!=nDestPgsz && sqlcipher_sqlite3PagerGetCodec(pDestPager)!=0 ){
+ if( nSrcPgsz!=nDestPgsz && sqlcipherPagerGetCodec(pDestPager)!=0 ){
rc = SQLITE_READONLY;
}
@@ -80865,7 +79181,9 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VdbeCheckMemInvariants(Mem *p){
/* The szMalloc field holds the correct memory allocation size */
assert( p->szMalloc==0
- || p->szMalloc==sqlcipher_sqlite3DbMallocSize(p->db,p->zMalloc) );
+ || (p->flags==MEM_Undefined
+ && p->szMalloc<=sqlcipher_sqlite3DbMallocSize(p->db,p->zMalloc))
+ || p->szMalloc==sqlcipher_sqlite3DbMallocSize(p->db,p->zMalloc));
/* If p holds a string or blob, the Mem.z must point to exactly
** one of the following:
@@ -80988,10 +79306,15 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc
#ifndef SQLITE_OMIT_UTF16
int rc;
#endif
+ assert( pMem!=0 );
assert( !sqlcipher_sqlite3VdbeMemIsRowSet(pMem) );
assert( desiredEnc==SQLITE_UTF8 || desiredEnc==SQLITE_UTF16LE
|| desiredEnc==SQLITE_UTF16BE );
- if( !(pMem->flags&MEM_Str) || pMem->enc==desiredEnc ){
+ if( !(pMem->flags&MEM_Str) ){
+ pMem->enc = desiredEnc;
+ return SQLITE_OK;
+ }
+ if( pMem->enc==desiredEnc ){
return SQLITE_OK;
}
assert( pMem->db==0 || sqlcipher_sqlite3_mutex_held(pMem->db->mutex) );
@@ -81029,7 +79352,9 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlcipher_sqlite3VdbeMemGrow(Mem *pMem, int n
testcase( bPreserve && pMem->z==0 );
assert( pMem->szMalloc==0
- || pMem->szMalloc==sqlcipher_sqlite3DbMallocSize(pMem->db, pMem->zMalloc) );
+ || (pMem->flags==MEM_Undefined
+ && pMem->szMalloc<=sqlcipher_sqlite3DbMallocSize(pMem->db,pMem->zMalloc))
+ || pMem->szMalloc==sqlcipher_sqlite3DbMallocSize(pMem->db,pMem->zMalloc));
if( pMem->szMalloc>0 && bPreserve && pMem->z==pMem->zMalloc ){
if( pMem->db ){
pMem->z = pMem->zMalloc = sqlcipher_sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
@@ -81118,6 +79443,7 @@ static SQLITE_NOINLINE int vdbeMemAddTerminator(Mem *pMem){
** Return SQLITE_OK on success or SQLITE_NOMEM if malloc fails.
*/
SQLITE_PRIVATE int sqlcipher_sqlite3VdbeMemMakeWriteable(Mem *pMem){
+ assert( pMem!=0 );
assert( pMem->db==0 || sqlcipher_sqlite3_mutex_held(pMem->db->mutex) );
assert( !sqlcipher_sqlite3VdbeMemIsRowSet(pMem) );
if( (pMem->flags & (MEM_Str|MEM_Blob))!=0 ){
@@ -81142,6 +79468,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VdbeMemMakeWriteable(Mem *pMem){
#ifndef SQLITE_OMIT_INCRBLOB
SQLITE_PRIVATE int sqlcipher_sqlite3VdbeMemExpandBlob(Mem *pMem){
int nByte;
+ assert( pMem!=0 );
assert( pMem->flags & MEM_Zero );
assert( (pMem->flags&MEM_Blob)!=0 || MemNullNochng(pMem) );
testcase( sqlcipher_sqlite3_value_nochange(pMem) );
@@ -81157,6 +79484,8 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VdbeMemExpandBlob(Mem *pMem){
if( sqlcipher_sqlite3VdbeMemGrow(pMem, nByte, 1) ){
return SQLITE_NOMEM_BKPT;
}
+ assert( pMem->z!=0 );
+ assert( sqlcipher_sqlite3DbMallocSize(pMem->db,pMem->z) >= nByte );
memset(&pMem->z[pMem->n], 0, pMem->u.nZero);
pMem->n += pMem->u.nZero;
@@ -81169,6 +79498,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VdbeMemExpandBlob(Mem *pMem){
** Make sure the given Mem is \u0000 terminated.
*/
SQLITE_PRIVATE int sqlcipher_sqlite3VdbeMemNulTerminate(Mem *pMem){
+ assert( pMem!=0 );
assert( pMem->db==0 || sqlcipher_sqlite3_mutex_held(pMem->db->mutex) );
testcase( (pMem->flags & (MEM_Term|MEM_Str))==(MEM_Term|MEM_Str) );
testcase( (pMem->flags & (MEM_Term|MEM_Str))==0 );
@@ -81196,6 +79526,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VdbeMemNulTerminate(Mem *pMem){
SQLITE_PRIVATE int sqlcipher_sqlite3VdbeMemStringify(Mem *pMem, u8 enc, u8 bForce){
const int nByte = 32;
+ assert( pMem!=0 );
assert( pMem->db==0 || sqlcipher_sqlite3_mutex_held(pMem->db->mutex) );
assert( !(pMem->flags&MEM_Zero) );
assert( !(pMem->flags&(MEM_Str|MEM_Blob)) );
@@ -81231,9 +79562,11 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){
sqlcipher_sqlite3_context ctx;
Mem t;
assert( pFunc!=0 );
+ assert( pMem!=0 );
+ assert( pMem->db!=0 );
assert( pFunc->xFinalize!=0 );
assert( (pMem->flags & MEM_Null)!=0 || pFunc==pMem->u.pDef );
- assert( pMem->db==0 || sqlcipher_sqlite3_mutex_held(pMem->db->mutex) );
+ assert( sqlcipher_sqlite3_mutex_held(pMem->db->mutex) );
memset(&ctx, 0, sizeof(ctx));
memset(&t, 0, sizeof(t));
t.flags = MEM_Null;
@@ -81241,6 +79574,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){
ctx.pOut = &t;
ctx.pMem = pMem;
ctx.pFunc = pFunc;
+ ctx.enc = ENC(t.db);
pFunc->xFinalize(&ctx); /* IMP: R-24505-23230 */
assert( (pMem->flags & MEM_Dyn)==0 );
if( pMem->szMalloc>0 ) sqlcipher_sqlite3DbFreeNN(pMem->db, pMem->zMalloc);
@@ -81262,12 +79596,14 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VdbeMemAggValue(Mem *pAccum, Mem *pOut, Func
assert( pFunc!=0 );
assert( pFunc->xValue!=0 );
assert( (pAccum->flags & MEM_Null)!=0 || pFunc==pAccum->u.pDef );
- assert( pAccum->db==0 || sqlcipher_sqlite3_mutex_held(pAccum->db->mutex) );
+ assert( pAccum->db!=0 );
+ assert( sqlcipher_sqlite3_mutex_held(pAccum->db->mutex) );
memset(&ctx, 0, sizeof(ctx));
sqlcipher_sqlite3VdbeMemSetNull(pOut);
ctx.pOut = pOut;
ctx.pMem = pAccum;
ctx.pFunc = pFunc;
+ ctx.enc = ENC(pAccum->db);
pFunc->xValue(&ctx);
return ctx.isError;
}
@@ -81333,6 +79669,14 @@ SQLITE_PRIVATE void sqlcipher_sqlite3VdbeMemRelease(Mem *p){
}
}
+/* Like sqlcipher_sqlite3VdbeMemRelease() but faster for cases where we
+** know in advance that the Mem is not MEM_Dyn or MEM_Agg.
+*/
+SQLITE_PRIVATE void sqlcipher_sqlite3VdbeMemReleaseMalloc(Mem *p){
+ assert( !VdbeMemDynamic(p) );
+ if( p->szMalloc ) vdbeMemClear(p);
+}
+
/*
** Convert a 64-bit IEEE double into a 64-bit signed integer.
** If the double is out of range of a 64-bit signed integer then
@@ -81374,13 +79718,14 @@ static SQLITE_NOINLINE i64 doubleToInt64(double r){
**
** If pMem represents a string value, its encoding might be changed.
*/
-static SQLITE_NOINLINE i64 memIntValue(Mem *pMem){
+static SQLITE_NOINLINE i64 memIntValue(const Mem *pMem){
i64 value = 0;
sqlcipher_sqlite3Atoi64(pMem->z, &value, pMem->n, pMem->enc);
return value;
}
-SQLITE_PRIVATE i64 sqlcipher_sqlite3VdbeIntValue(Mem *pMem){
+SQLITE_PRIVATE i64 sqlcipher_sqlite3VdbeIntValue(const Mem *pMem){
int flags;
+ assert( pMem!=0 );
assert( pMem->db==0 || sqlcipher_sqlite3_mutex_held(pMem->db->mutex) );
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
flags = pMem->flags;
@@ -81409,6 +79754,7 @@ static SQLITE_NOINLINE double memRealValue(Mem *pMem){
return val;
}
SQLITE_PRIVATE double sqlcipher_sqlite3VdbeRealValue(Mem *pMem){
+ assert( pMem!=0 );
assert( pMem->db==0 || sqlcipher_sqlite3_mutex_held(pMem->db->mutex) );
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
if( pMem->flags & MEM_Real ){
@@ -81441,6 +79787,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VdbeBooleanValue(Mem *pMem, int ifNull){
*/
SQLITE_PRIVATE void sqlcipher_sqlite3VdbeIntegerAffinity(Mem *pMem){
i64 ix;
+ assert( pMem!=0 );
assert( pMem->flags & MEM_Real );
assert( !sqlcipher_sqlite3VdbeMemIsRowSet(pMem) );
assert( pMem->db==0 || sqlcipher_sqlite3_mutex_held(pMem->db->mutex) );
@@ -81468,6 +79815,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3VdbeIntegerAffinity(Mem *pMem){
** Convert pMem to type integer. Invalidate any prior representations.
*/
SQLITE_PRIVATE int sqlcipher_sqlite3VdbeMemIntegerify(Mem *pMem){
+ assert( pMem!=0 );
assert( pMem->db==0 || sqlcipher_sqlite3_mutex_held(pMem->db->mutex) );
assert( !sqlcipher_sqlite3VdbeMemIsRowSet(pMem) );
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
@@ -81482,6 +79830,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VdbeMemIntegerify(Mem *pMem){
** Invalidate any prior representations.
*/
SQLITE_PRIVATE int sqlcipher_sqlite3VdbeMemRealify(Mem *pMem){
+ assert( pMem!=0 );
assert( pMem->db==0 || sqlcipher_sqlite3_mutex_held(pMem->db->mutex) );
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
@@ -81515,6 +79864,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3RealSameAsInt(double r1, sqlcipher_sqlite3_i
** as much of the string as we can and ignore the rest.
*/
SQLITE_PRIVATE int sqlcipher_sqlite3VdbeMemNumerify(Mem *pMem){
+ assert( pMem!=0 );
testcase( pMem->flags & MEM_Int );
testcase( pMem->flags & MEM_Real );
testcase( pMem->flags & MEM_IntReal );
@@ -81624,6 +79974,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3ValueSetNull(sqlcipher_sqlite3_value *p){
** Delete any previous value and set the value to be a BLOB of length
** n containing all zeros.
*/
+#ifndef SQLITE_OMIT_INCRBLOB
SQLITE_PRIVATE void sqlcipher_sqlite3VdbeMemSetZeroBlob(Mem *pMem, int n){
sqlcipher_sqlite3VdbeMemRelease(pMem);
pMem->flags = MEM_Blob|MEM_Zero;
@@ -81633,6 +79984,21 @@ SQLITE_PRIVATE void sqlcipher_sqlite3VdbeMemSetZeroBlob(Mem *pMem, int n){
pMem->enc = SQLITE_UTF8;
pMem->z = 0;
}
+#else
+SQLITE_PRIVATE int sqlcipher_sqlite3VdbeMemSetZeroBlob(Mem *pMem, int n){
+ int nByte = n>0?n:1;
+ if( sqlcipher_sqlite3VdbeMemGrow(pMem, nByte, 0) ){
+ return SQLITE_NOMEM_BKPT;
+ }
+ assert( pMem->z!=0 );
+ assert( sqlcipher_sqlite3DbMallocSize(pMem->db, pMem->z)>=nByte );
+ memset(pMem->z, 0, nByte);
+ pMem->n = n>0?n:0;
+ pMem->flags = MEM_Blob;
+ pMem->enc = SQLITE_UTF8;
+ return SQLITE_OK;
+}
+#endif
/*
** The pMem is known to contain content that needs to be destroyed prior
@@ -81672,6 +80038,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3VdbeMemSetPointer(
void (*xDestructor)(void*)
){
assert( pMem->flags==MEM_Null );
+ vdbeMemClear(pMem);
pMem->u.zPType = zPType ? zPType : "";
pMem->z = pPtr;
pMem->flags = MEM_Null|MEM_Dyn|MEM_Subtype|MEM_Term;
@@ -81854,20 +80221,29 @@ SQLITE_PRIVATE void sqlcipher_sqlite3VdbeMemMove(Mem *pTo, Mem *pFrom){
** stored without allocating memory, then it is. If a memory allocation
** is required to store the string, then value of pMem is unchanged. In
** either case, SQLITE_TOOBIG is returned.
+**
+** The "enc" parameter is the text encoding for the string, or zero
+** to store a blob.
+**
+** If n is negative, then the string consists of all bytes up to but
+** excluding the first zero character. The n parameter must be
+** non-negative for blobs.
*/
SQLITE_PRIVATE int sqlcipher_sqlite3VdbeMemSetStr(
Mem *pMem, /* Memory cell to set to string value */
const char *z, /* String pointer */
- int n, /* Bytes in string, or negative */
+ i64 n, /* Bytes in string, or negative */
u8 enc, /* Encoding of z. 0 for BLOBs */
void (*xDel)(void*) /* Destructor function */
){
- int nByte = n; /* New value for pMem->n */
+ i64 nByte = n; /* New value for pMem->n */
int iLimit; /* Maximum allowed string or blob size */
- u16 flags = 0; /* New value for pMem->flags */
+ u16 flags; /* New value for pMem->flags */
+ assert( pMem!=0 );
assert( pMem->db==0 || sqlcipher_sqlite3_mutex_held(pMem->db->mutex) );
assert( !sqlcipher_sqlite3VdbeMemIsRowSet(pMem) );
+ assert( enc!=0 || n>=0 );
/* If z is a NULL pointer, set pMem to contain an SQL NULL. */
if( !z ){
@@ -81880,15 +80256,30 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VdbeMemSetStr(
}else{
iLimit = SQLITE_MAX_LENGTH;
}
- flags = (enc==0?MEM_Blob:MEM_Str);
if( nByte<0 ){
assert( enc!=0 );
if( enc==SQLITE_UTF8 ){
- nByte = 0x7fffffff & (int)strlen(z);
+ nByte = strlen(z);
}else{
for(nByte=0; nByte<=iLimit && (z[nByte] | z[nByte+1]); nByte+=2){}
}
- flags |= MEM_Term;
+ flags= MEM_Str|MEM_Term;
+ }else if( enc==0 ){
+ flags = MEM_Blob;
+ enc = SQLITE_UTF8;
+ }else{
+ flags = MEM_Str;
+ }
+ if( nByte>iLimit ){
+ if( xDel && xDel!=SQLITE_TRANSIENT ){
+ if( xDel==SQLITE_DYNAMIC ){
+ sqlcipher_sqlite3DbFree(pMem->db, (void*)z);
+ }else{
+ xDel((void*)z);
+ }
+ }
+ sqlcipher_sqlite3VdbeMemSetNull(pMem);
+ return sqlcipher_sqlite3ErrorToParser(pMem->db, SQLITE_TOOBIG);
}
/* The following block sets the new values of Mem.z and Mem.xDel. It
@@ -81896,13 +80287,10 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VdbeMemSetStr(
** management (one of MEM_Dyn or MEM_Static).
*/
if( xDel==SQLITE_TRANSIENT ){
- u32 nAlloc = nByte;
+ i64 nAlloc = nByte;
if( flags&MEM_Term ){
nAlloc += (enc==SQLITE_UTF8?1:2);
}
- if( nByte>iLimit ){
- return sqlcipher_sqlite3ErrorToParser(pMem->db, SQLITE_TOOBIG);
- }
testcase( nAlloc==0 );
testcase( nAlloc==31 );
testcase( nAlloc==32 );
@@ -81922,18 +80310,9 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VdbeMemSetStr(
}
}
- pMem->n = nByte;
+ pMem->n = (int)(nByte & 0x7fffffff);
pMem->flags = flags;
- if( enc ){
- pMem->enc = enc;
-#ifdef SQLITE_ENABLE_SESSION
- }else if( pMem->db==0 ){
- pMem->enc = SQLITE_UTF8;
-#endif
- }else{
- assert( pMem->db!=0 );
- pMem->enc = ENC(pMem->db);
- }
+ pMem->enc = enc;
#ifndef SQLITE_OMIT_UTF16
if( enc>SQLITE_UTF8 && sqlcipher_sqlite3VdbeMemHandleBom(pMem) ){
@@ -81941,9 +80320,6 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VdbeMemSetStr(
}
#endif
- if( nByte>iLimit ){
- return SQLITE_TOOBIG;
- }
return SQLITE_OK;
}
@@ -82174,7 +80550,7 @@ static sqlcipher_sqlite3_value *valueNew(sqlcipher_sqlite3 *db, struct ValueNewS
#ifdef SQLITE_ENABLE_STAT4
static int valueFromFunction(
sqlcipher_sqlite3 *db, /* The database connection */
- Expr *p, /* The expression to evaluate */
+ const Expr *p, /* The expression to evaluate */
u8 enc, /* Encoding to use */
u8 aff, /* Affinity to use */
sqlcipher_sqlite3_value **ppVal, /* Write the new value here */
@@ -82191,8 +80567,10 @@ static int valueFromFunction(
assert( pCtx!=0 );
assert( (p->flags & EP_TokenOnly)==0 );
+ assert( ExprUseXList(p) );
pList = p->x.pList;
if( pList ) nVal = pList->nExpr;
+ assert( !ExprHasProperty(p, EP_IntValue) );
pFunc = sqlcipher_sqlite3FindFunction(db, p->u.zToken, nVal, enc, 0);
assert( pFunc );
if( (pFunc->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG))==0
@@ -82219,10 +80597,12 @@ static int valueFromFunction(
goto value_from_function_out;
}
- assert( pCtx->pParse->rc==SQLITE_OK );
+ testcase( pCtx->pParse->rc==SQLITE_ERROR );
+ testcase( pCtx->pParse->rc==SQLITE_OK );
memset(&ctx, 0, sizeof(ctx));
ctx.pOut = pVal;
ctx.pFunc = pFunc;
+ ctx.enc = ENC(db);
pFunc->xSFunc(&ctx, nVal, apVal);
if( ctx.isError ){
rc = ctx.isError;
@@ -82268,7 +80648,7 @@ static int valueFromFunction(
*/
static int valueFromExpr(
sqlcipher_sqlite3 *db, /* The database connection */
- Expr *pExpr, /* The expression to evaluate */
+ const Expr *pExpr, /* The expression to evaluate */
u8 enc, /* Encoding to use */
u8 affinity, /* Affinity to use */
sqlcipher_sqlite3_value **ppVal, /* Write the new value here */
@@ -82283,11 +80663,7 @@ static int valueFromExpr(
assert( pExpr!=0 );
while( (op = pExpr->op)==TK_UPLUS || op==TK_SPAN ) pExpr = pExpr->pLeft;
-#if defined(SQLITE_ENABLE_STAT4)
if( op==TK_REGISTER ) op = pExpr->op2;
-#else
- if( NEVER(op==TK_REGISTER) ) op = pExpr->op2;
-#endif
/* Compressed expressions only appear when parsing the DEFAULT clause
** on a table column definition, and hence only when pCtx==0. This
@@ -82296,12 +80672,14 @@ static int valueFromExpr(
assert( (pExpr->flags & EP_TokenOnly)==0 || pCtx==0 );
if( op==TK_CAST ){
- u8 aff = sqlcipher_sqlite3AffinityType(pExpr->u.zToken,0);
+ u8 aff;
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
+ aff = sqlcipher_sqlite3AffinityType(pExpr->u.zToken,0);
rc = valueFromExpr(db, pExpr->pLeft, enc, aff, ppVal, pCtx);
testcase( rc!=SQLITE_OK );
if( *ppVal ){
- sqlcipher_sqlite3VdbeMemCast(*ppVal, aff, SQLITE_UTF8);
- sqlcipher_sqlite3ValueApplyAffinity(*ppVal, affinity, SQLITE_UTF8);
+ sqlcipher_sqlite3VdbeMemCast(*ppVal, aff, enc);
+ sqlcipher_sqlite3ValueApplyAffinity(*ppVal, affinity, enc);
}
return rc;
}
@@ -82369,6 +80747,7 @@ static int valueFromExpr(
#ifndef SQLITE_OMIT_BLOB_LITERAL
else if( op==TK_BLOB ){
int nVal;
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
assert( pExpr->u.zToken[0]=='x' || pExpr->u.zToken[0]=='X' );
assert( pExpr->u.zToken[1]=='\'' );
pVal = valueNew(db, pCtx);
@@ -82386,6 +80765,7 @@ static int valueFromExpr(
}
#endif
else if( op==TK_TRUEFALSE ){
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
pVal = valueNew(db, pCtx);
if( pVal ){
pVal->flags = MEM_Int;
@@ -82398,7 +80778,7 @@ static int valueFromExpr(
no_mem:
#ifdef SQLITE_ENABLE_STAT4
- if( pCtx==0 || pCtx->pParse->nErr==0 )
+ if( pCtx==0 || NEVER(pCtx->pParse->nErr==0) )
#endif
sqlcipher_sqlite3OomFault(db);
sqlcipher_sqlite3DbFree(db, zVal);
@@ -82423,7 +80803,7 @@ no_mem:
*/
SQLITE_PRIVATE int sqlcipher_sqlite3ValueFromExpr(
sqlcipher_sqlite3 *db, /* The database connection */
- Expr *pExpr, /* The expression to evaluate */
+ const Expr *pExpr, /* The expression to evaluate */
u8 enc, /* Encoding to use */
u8 affinity, /* Affinity to use */
sqlcipher_sqlite3_value **ppVal /* Write the new value here */
@@ -82733,7 +81113,7 @@ SQLITE_PRIVATE Vdbe *sqlcipher_sqlite3VdbeCreate(Parse *pParse){
p->pNext = db->pVdbe;
p->pPrev = 0;
db->pVdbe = p;
- p->magic = VDBE_MAGIC_INIT;
+ assert( p->eVdbeState==VDBE_INIT_STATE );
p->pParse = pParse;
pParse->pVdbe = p;
assert( pParse->aLabel==0 );
@@ -82878,7 +81258,7 @@ static int growOpArray(Vdbe *v, int nOp){
return SQLITE_NOMEM;
}
- assert( nOp<=(1024/sizeof(Op)) );
+ assert( nOp<=(int)(1024/sizeof(Op)) );
assert( nNew>=(v->nOpAlloc+nOp) );
pNew = sqlcipher_sqlite3DbRealloc(p->db, v->aOp, nNew*sizeof(Op));
if( pNew ){
@@ -82934,13 +81314,15 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2,
VdbeOp *pOp;
i = p->nOp;
- assert( p->magic==VDBE_MAGIC_INIT );
+ assert( p->eVdbeState==VDBE_INIT_STATE );
assert( op>=0 && op<0xff );
if( p->nOpAlloc<=i ){
return growOp3(p, op, p1, p2, p3);
}
+ assert( p->aOp!=0 );
p->nOp++;
pOp = &p->aOp[i];
+ assert( pOp!=0 );
pOp->opcode = (u8)op;
pOp->p5 = 0;
pOp->p1 = p1;
@@ -83077,6 +81459,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VdbeAddFunctionCall(
addr = sqlcipher_sqlite3VdbeAddOp4(v, eCallCtx ? OP_PureFunc : OP_Function,
p1, p2, p3, (char*)pCtx, P4_FUNCCTX);
sqlcipher_sqlite3VdbeChangeP5(v, eCallCtx & NC_SelfRef);
+ sqlcipher_sqlite3MayAbort(pParse);
return addr;
}
@@ -83169,9 +81552,10 @@ SQLITE_PRIVATE void sqlcipher_sqlite3VdbeExplainPop(Parse *pParse){
** The zWhere string must have been obtained from sqlcipher_sqlite3_malloc().
** This routine will take ownership of the allocated memory.
*/
-SQLITE_PRIVATE void sqlcipher_sqlite3VdbeAddParseSchemaOp(Vdbe *p, int iDb, char *zWhere){
+SQLITE_PRIVATE void sqlcipher_sqlite3VdbeAddParseSchemaOp(Vdbe *p, int iDb, char *zWhere, u16 p5){
int j;
sqlcipher_sqlite3VdbeAddOp4(p, OP_ParseSchema, iDb, 0, 0, zWhere, P4_DYNAMIC);
+ sqlcipher_sqlite3VdbeChangeP5(p, p5);
for(j=0; j<p->db->nDb; j++) sqlcipher_sqlite3VdbeUsesBtree(p, j);
sqlcipher_sqlite3MayAbort(p->pParse);
}
@@ -83263,7 +81647,7 @@ static SQLITE_NOINLINE void resizeResolveLabel(Parse *p, Vdbe *v, int j){
SQLITE_PRIVATE void sqlcipher_sqlite3VdbeResolveLabel(Vdbe *v, int x){
Parse *p = v->pParse;
int j = ADDR(x);
- assert( v->magic==VDBE_MAGIC_INIT );
+ assert( v->eVdbeState==VDBE_INIT_STATE );
assert( j<-p->nLabel );
assert( j>=0 );
#ifdef SQLITE_DEBUG
@@ -83283,14 +81667,20 @@ SQLITE_PRIVATE void sqlcipher_sqlite3VdbeResolveLabel(Vdbe *v, int x){
** Mark the VDBE as one that can only be run one time.
*/
SQLITE_PRIVATE void sqlcipher_sqlite3VdbeRunOnlyOnce(Vdbe *p){
- p->runOnlyOnce = 1;
+ sqlcipher_sqlite3VdbeAddOp2(p, OP_Expire, 1, 1);
}
/*
-** Mark the VDBE as one that can only be run multiple times.
+** Mark the VDBE as one that can be run multiple times.
*/
SQLITE_PRIVATE void sqlcipher_sqlite3VdbeReusable(Vdbe *p){
- p->runOnlyOnce = 0;
+ int i;
+ for(i=1; ALWAYS(i<p->nOp); i++){
+ if( ALWAYS(p->aOp[i].opcode==OP_Expire) ){
+ p->aOp[1].opcode = OP_Noop;
+ break;
+ }
+ }
}
#ifdef SQLITE_DEBUG /* sqlcipher_sqlite3AssertMayAbort() logic */
@@ -83394,6 +81784,8 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
int hasInitCoroutine = 0;
Op *pOp;
VdbeOpIter sIter;
+
+ if( v==0 ) return 0;
memset(&sIter, 0, sizeof(sIter));
sIter.v = v;
@@ -83403,6 +81795,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
|| opcode==OP_VDestroy
|| opcode==OP_VCreate
|| opcode==OP_ParseSchema
+ || opcode==OP_Function || opcode==OP_PureFunc
|| ((opcode==OP_Halt || opcode==OP_HaltIfNull)
&& ((pOp->p1)!=SQLITE_OK && pOp->p2==OE_Abort))
){
@@ -83477,7 +81870,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3VdbeAssertAbortable(Vdbe *p){
** (3) Update the Vdbe.readOnly and Vdbe.bIsReader flags to accurately
** indicate what the prepared statement actually does.
**
-** (4) Initialize the p4.xAdvance pointer on opcodes that use it.
+** (4) (discontinued)
**
** (5) Reclaim the memory allocated for storing labels.
**
@@ -83523,25 +81916,6 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
p->bIsReader = 1;
break;
}
- case OP_Next:
- case OP_SorterNext: {
- pOp->p4.xAdvance = sqlcipher_sqlite3BtreeNext;
- pOp->p4type = P4_ADVANCE;
- /* The code generator never codes any of these opcodes as a jump
- ** to a label. They are always coded as a jump backwards to a
- ** known address */
- assert( pOp->p2>=0 );
- break;
- }
- case OP_Prev: {
- pOp->p4.xAdvance = sqlcipher_sqlite3BtreePrevious;
- pOp->p4type = P4_ADVANCE;
- /* The code generator never codes any of these opcodes as a jump
- ** to a label. They are always coded as a jump backwards to a
- ** known address */
- assert( pOp->p2>=0 );
- break;
- }
#ifndef SQLITE_OMIT_VIRTUALTABLE
case OP_VUpdate: {
if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2;
@@ -83577,18 +81951,104 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
if( pOp==p->aOp ) break;
pOp--;
}
- sqlcipher_sqlite3DbFree(p->db, pParse->aLabel);
- pParse->aLabel = 0;
+ if( aLabel ){
+ sqlcipher_sqlite3DbFreeNN(p->db, pParse->aLabel);
+ pParse->aLabel = 0;
+ }
pParse->nLabel = 0;
*pMaxFuncArgs = nMaxArgs;
assert( p->bIsReader!=0 || DbMaskAllZero(p->btreeMask) );
}
+#ifdef SQLITE_DEBUG
+/*
+** Check to see if a subroutine contains a jump to a location outside of
+** the subroutine. If a jump outside the subroutine is detected, add code
+** that will cause the program to halt with an error message.
+**
+** The subroutine consists of opcodes between iFirst and iLast. Jumps to
+** locations within the subroutine are acceptable. iRetReg is a register
+** that contains the return address. Jumps to outside the range of iFirst
+** through iLast are also acceptable as long as the jump destination is
+** an OP_Return to iReturnAddr.
+**
+** A jump to an unresolved label means that the jump destination will be
+** beyond the current address. That is normally a jump to an early
+** termination and is consider acceptable.
+**
+** This routine only runs during debug builds. The purpose is (of course)
+** to detect invalid escapes out of a subroutine. The OP_Halt opcode
+** is generated rather than an assert() or other error, so that ".eqp full"
+** will still work to show the original bytecode, to aid in debugging.
+*/
+SQLITE_PRIVATE void sqlcipher_sqlite3VdbeNoJumpsOutsideSubrtn(
+ Vdbe *v, /* The byte-code program under construction */
+ int iFirst, /* First opcode of the subroutine */
+ int iLast, /* Last opcode of the subroutine */
+ int iRetReg /* Subroutine return address register */
+){
+ VdbeOp *pOp;
+ Parse *pParse;
+ int i;
+ sqlcipher_sqlite3_str *pErr = 0;
+ assert( v!=0 );
+ pParse = v->pParse;
+ assert( pParse!=0 );
+ if( pParse->nErr ) return;
+ assert( iLast>=iFirst );
+ assert( iLast<v->nOp );
+ pOp = &v->aOp[iFirst];
+ for(i=iFirst; i<=iLast; i++, pOp++){
+ if( (sqlcipher_sqlite3OpcodeProperty[pOp->opcode] & OPFLG_JUMP)!=0 ){
+ int iDest = pOp->p2; /* Jump destination */
+ if( iDest==0 ) continue;
+ if( pOp->opcode==OP_Gosub ) continue;
+ if( iDest<0 ){
+ int j = ADDR(iDest);
+ assert( j>=0 );
+ if( j>=-pParse->nLabel || pParse->aLabel[j]<0 ){
+ continue;
+ }
+ iDest = pParse->aLabel[j];
+ }
+ if( iDest<iFirst || iDest>iLast ){
+ int j = iDest;
+ for(; j<v->nOp; j++){
+ VdbeOp *pX = &v->aOp[j];
+ if( pX->opcode==OP_Return ){
+ if( pX->p1==iRetReg ) break;
+ continue;
+ }
+ if( pX->opcode==OP_Noop ) continue;
+ if( pX->opcode==OP_Explain ) continue;
+ if( pErr==0 ){
+ pErr = sqlcipher_sqlite3_str_new(0);
+ }else{
+ sqlcipher_sqlite3_str_appendchar(pErr, 1, '\n');
+ }
+ sqlcipher_sqlite3_str_appendf(pErr,
+ "Opcode at %d jumps to %d which is outside the "
+ "subroutine at %d..%d",
+ i, iDest, iFirst, iLast);
+ break;
+ }
+ }
+ }
+ }
+ if( pErr ){
+ char *zErr = sqlcipher_sqlite3_str_finish(pErr);
+ sqlcipher_sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_INTERNAL, OE_Abort, 0, zErr, 0);
+ sqlcipher_sqlite3_free(zErr);
+ sqlcipher_sqlite3MayAbort(pParse);
+ }
+}
+#endif /* SQLITE_DEBUG */
+
/*
** Return the address of the next instruction to be inserted.
*/
SQLITE_PRIVATE int sqlcipher_sqlite3VdbeCurrentAddr(Vdbe *p){
- assert( p->magic==VDBE_MAGIC_INIT );
+ assert( p->eVdbeState==VDBE_INIT_STATE );
return p->nOp;
}
@@ -83673,7 +82133,7 @@ SQLITE_PRIVATE VdbeOp *sqlcipher_sqlite3VdbeAddOpList(
int i;
VdbeOp *pOut, *pFirst;
assert( nOp>0 );
- assert( p->magic==VDBE_MAGIC_INIT );
+ assert( p->eVdbeState==VDBE_INIT_STATE );
if( p->nOp + nOp > p->nOpAlloc && growOpArray(p, nOp) ){
return 0;
}
@@ -83825,7 +82285,6 @@ static void freeP4(sqlcipher_sqlite3 *db, int p4type, void *p4){
case P4_REAL:
case P4_INT64:
case P4_DYNAMIC:
- case P4_DYNBLOB:
case P4_INTARRAY: {
sqlcipher_sqlite3DbFree(db, p4);
break;
@@ -83865,13 +82324,16 @@ static void freeP4(sqlcipher_sqlite3 *db, int p4type, void *p4){
** nOp entries.
*/
static void vdbeFreeOpArray(sqlcipher_sqlite3 *db, Op *aOp, int nOp){
+ assert( nOp>=0 );
if( aOp ){
- Op *pOp;
- for(pOp=&aOp[nOp-1]; pOp>=aOp; pOp--){
+ Op *pOp = &aOp[nOp-1];
+ while(1){ /* Exit via break */
if( pOp->p4type <= P4_FREE_IF_LE ) freeP4(db, pOp->p4type, pOp->p4.p);
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
sqlcipher_sqlite3DbFree(db, pOp->zComment);
#endif
+ if( pOp==aOp ) break;
+ pOp--;
}
sqlcipher_sqlite3DbFreeNN(db, aOp);
}
@@ -83933,7 +82395,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3VdbeReleaseRegisters(
u32 mask, /* Mask of registers to NOT release */
int bUndefine /* If true, mark registers as undefined */
){
- if( N==0 ) return;
+ if( N==0 || OptimizationDisabled(pParse->db, SQLITE_ReleaseReg) ) return;
assert( pParse->pVdbe );
assert( iFirst>=1 );
assert( iFirst+N-1<=pParse->nMem );
@@ -83997,7 +82459,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3VdbeChangeP4(Vdbe *p, int addr, const char
sqlcipher_sqlite3 *db;
assert( p!=0 );
db = p->db;
- assert( p->magic==VDBE_MAGIC_INIT );
+ assert( p->eVdbeState==VDBE_INIT_STATE );
assert( p->aOp!=0 || db->mallocFailed );
if( db->mallocFailed ){
if( n!=P4_VTAB ) freeP4(db, n, (void*)*(char**)&zP4);
@@ -84073,8 +82535,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3VdbeSetP4KeyInfo(Parse *pParse, Index *pIdx
*/
static void vdbeVComment(Vdbe *p, const char *zFormat, va_list ap){
assert( p->nOp>0 || p->aOp==0 );
- assert( p->aOp==0 || p->aOp[p->nOp-1].zComment==0 || p->db->mallocFailed
- || p->pParse->nErr>0 );
+ assert( p->aOp==0 || p->aOp[p->nOp-1].zComment==0 || p->pParse->nErr>0 );
if( p->nOp ){
assert( p->aOp );
sqlcipher_sqlite3DbFree(p->db, p->aOp[p->nOp-1].zComment);
@@ -84126,7 +82587,7 @@ SQLITE_PRIVATE VdbeOp *sqlcipher_sqlite3VdbeGetOp(Vdbe *p, int addr){
/* C89 specifies that the constant "dummy" will be initialized to all
** zeros, which is correct. MSVC generates a warning, nevertheless. */
static VdbeOp dummy; /* Ignore the MSVC warning about no initializer */
- assert( p->magic==VDBE_MAGIC_INIT );
+ assert( p->eVdbeState==VDBE_INIT_STATE );
if( addr<0 ){
addr = p->nOp - 1;
}
@@ -84182,13 +82643,9 @@ SQLITE_PRIVATE char *sqlcipher_sqlite3VdbeDisplayComment(
if( zOpName[nOpName+1] ){
int seenCom = 0;
char c;
- zSynopsis = zOpName += nOpName + 1;
+ zSynopsis = zOpName + nOpName + 1;
if( strncmp(zSynopsis,"IF ",3)==0 ){
- if( pOp->p5 & SQLITE_STOREP2 ){
- sqlcipher_sqlite3_snprintf(sizeof(zAlt), zAlt, "r[P2] = (%s)", zSynopsis+3);
- }else{
- sqlcipher_sqlite3_snprintf(sizeof(zAlt), zAlt, "if %s goto P2", zSynopsis+3);
- }
+ sqlcipher_sqlite3_snprintf(sizeof(zAlt), zAlt, "if %s goto P2", zSynopsis+3);
zSynopsis = zAlt;
}
for(ii=0; (c = zSynopsis[ii])!=0; ii++){
@@ -84197,8 +82654,11 @@ SQLITE_PRIVATE char *sqlcipher_sqlite3VdbeDisplayComment(
if( c=='4' ){
sqlcipher_sqlite3_str_appendall(&x, zP4);
}else if( c=='X' ){
- sqlcipher_sqlite3_str_appendall(&x, pOp->zComment);
- seenCom = 1;
+ if( pOp->zComment && pOp->zComment[0] ){
+ sqlcipher_sqlite3_str_appendall(&x, pOp->zComment);
+ seenCom = 1;
+ break;
+ }
}else{
int v1 = translateP(c, pOp);
int v2;
@@ -84259,6 +82719,7 @@ static void displayP4Expr(StrAccum *p, Expr *pExpr){
const char *zOp = 0;
switch( pExpr->op ){
case TK_STRING:
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
sqlcipher_sqlite3_str_appendf(p, "%Q", pExpr->u.zToken);
break;
case TK_INTEGER:
@@ -84361,7 +82822,7 @@ SQLITE_PRIVATE char *sqlcipher_sqlite3VdbeDisplayP4(sqlcipher_sqlite3 *db, Op *p
case P4_COLLSEQ: {
static const char *const encnames[] = {"?", "8", "16LE", "16BE"};
CollSeq *pColl = pOp->p4.pColl;
- assert( pColl->enc>=0 && pColl->enc<4 );
+ assert( pColl->enc<4 );
sqlcipher_sqlite3_str_appendf(&x, "%.18s-%s", pColl->zName,
encnames[pColl->enc]);
break;
@@ -84426,10 +82887,6 @@ SQLITE_PRIVATE char *sqlcipher_sqlite3VdbeDisplayP4(sqlcipher_sqlite3 *db, Op *p
zP4 = "program";
break;
}
- case P4_DYNBLOB:
- case P4_ADVANCE: {
- break;
- }
case P4_TABLE: {
zP4 = pOp->p4.pTab->zName;
break;
@@ -84561,21 +83018,40 @@ SQLITE_PRIVATE void sqlcipher_sqlite3VdbePrintOp(FILE *pOut, int pc, VdbeOp *pOp
/*
** Initialize an array of N Mem element.
+**
+** This is a high-runner, so only those fields that really do need to
+** be initialized are set. The Mem structure is organized so that
+** the fields that get initialized are nearby and hopefully on the same
+** cache line.
+**
+** Mem.flags = flags
+** Mem.db = db
+** Mem.szMalloc = 0
+**
+** All other fields of Mem can safely remain uninitialized for now. They
+** will be initialized before use.
*/
static void initMemArray(Mem *p, int N, sqlcipher_sqlite3 *db, u16 flags){
- while( (N--)>0 ){
- p->db = db;
- p->flags = flags;
- p->szMalloc = 0;
+ if( N>0 ){
+ do{
+ p->flags = flags;
+ p->db = db;
+ p->szMalloc = 0;
#ifdef SQLITE_DEBUG
- p->pScopyFrom = 0;
+ p->pScopyFrom = 0;
#endif
- p++;
+ p++;
+ }while( (--N)>0 );
}
}
/*
-** Release an array of N Mem elements
+** Release auxiliary memory held in an array of N Mem elements.
+**
+** After this routine returns, all Mem elements in the array will still
+** be valid. Those Mem elements that were not holding auxiliary resources
+** will be unchanged. Mem elements which had something freed will be
+** set to MEM_Undefined.
*/
static void releaseMemArray(Mem *p, int N){
if( p && N ){
@@ -84605,15 +83081,20 @@ static void releaseMemArray(Mem *p, int N){
*/
testcase( p->flags & MEM_Agg );
testcase( p->flags & MEM_Dyn );
- testcase( p->xDel==sqlcipher_sqlite3VdbeFrameMemDel );
if( p->flags&(MEM_Agg|MEM_Dyn) ){
+ testcase( (p->flags & MEM_Dyn)!=0 && p->xDel==sqlcipher_sqlite3VdbeFrameMemDel );
sqlcipher_sqlite3VdbeMemRelease(p);
+ p->flags = MEM_Undefined;
}else if( p->szMalloc ){
sqlcipher_sqlite3DbFreeNN(db, p->zMalloc);
p->szMalloc = 0;
+ p->flags = MEM_Undefined;
}
-
- p->flags = MEM_Undefined;
+#ifdef SQLITE_DEBUG
+ else{
+ p->flags = MEM_Undefined;
+ }
+#endif
}while( (++p)<pEnd );
}
}
@@ -84772,7 +83253,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3VdbeFrameDelete(VdbeFrame *p){
VdbeCursor **apCsr = (VdbeCursor **)&aMem[p->nChildMem];
assert( sqlcipher_sqlite3VdbeFrameIsValid(p) );
for(i=0; i<p->nChildCsr; i++){
- sqlcipher_sqlite3VdbeFreeCursor(p->v, apCsr[i]);
+ if( apCsr[i] ) sqlcipher_sqlite3VdbeFreeCursorNN(p->v, apCsr[i]);
}
releaseMemArray(aMem, p->nChildMem);
sqlcipher_sqlite3VdbeDeleteAuxData(p->v->db, &p->pAuxData, -1, 0);
@@ -84811,7 +83292,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VdbeList(
Op *pOp; /* Current opcode */
assert( p->explain );
- assert( p->magic==VDBE_MAGIC_RUN );
+ assert( p->eVdbeState==VDBE_RUN_STATE );
assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY || p->rc==SQLITE_NOMEM );
/* Even though this opcode does not use dynamic strings for
@@ -84966,11 +83447,11 @@ struct ReusableSpace {
static void *allocSpace(
struct ReusableSpace *p, /* Bulk memory available for allocation */
void *pBuf, /* Pointer to a prior allocation */
- sqlcipher_sqlite3_int64 nByte /* Bytes of memory needed */
+ sqlcipher_sqlite3_int64 nByte /* Bytes of memory needed. */
){
assert( EIGHT_BYTE_ALIGNMENT(p->pSpace) );
if( pBuf==0 ){
- nByte = ROUND8(nByte);
+ nByte = ROUND8P(nByte);
if( nByte <= p->nFree ){
p->nFree -= nByte;
pBuf = &p->pSpace[p->nFree];
@@ -84991,14 +83472,15 @@ SQLITE_PRIVATE void sqlcipher_sqlite3VdbeRewind(Vdbe *p){
int i;
#endif
assert( p!=0 );
- assert( p->magic==VDBE_MAGIC_INIT || p->magic==VDBE_MAGIC_RESET );
+ assert( p->eVdbeState==VDBE_INIT_STATE
+ || p->eVdbeState==VDBE_READY_STATE
+ || p->eVdbeState==VDBE_HALT_STATE );
/* There should be at least one opcode.
*/
assert( p->nOp>0 );
- /* Set the magic to VDBE_MAGIC_RUN sooner rather than later. */
- p->magic = VDBE_MAGIC_RUN;
+ p->eVdbeState = VDBE_READY_STATE;
#ifdef SQLITE_DEBUG
for(i=0; i<p->nMem; i++){
@@ -85054,8 +83536,10 @@ SQLITE_PRIVATE void sqlcipher_sqlite3VdbeMakeReady(
assert( p!=0 );
assert( p->nOp>0 );
assert( pParse!=0 );
- assert( p->magic==VDBE_MAGIC_INIT );
+ assert( p->eVdbeState==VDBE_INIT_STATE );
assert( pParse==p->pParse );
+ p->pVList = pParse->pVList;
+ pParse->pVList = 0;
db = p->db;
assert( db->mallocFailed==0 );
nVar = pParse->nVar;
@@ -85075,7 +83559,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3VdbeMakeReady(
** opcode array. This extra memory will be reallocated for other elements
** of the prepared statement.
*/
- n = ROUND8(sizeof(Op)*p->nOp); /* Bytes of opcode memory used */
+ n = ROUND8P(sizeof(Op)*p->nOp); /* Bytes of opcode memory used */
x.pSpace = &((u8*)p->aOp)[n]; /* Unused opcode memory */
assert( EIGHT_BYTE_ALIGNMENT(x.pSpace) );
x.nFree = ROUNDDOWN8(pParse->szOpAlloc - n); /* Bytes of unused memory */
@@ -85140,8 +83624,6 @@ SQLITE_PRIVATE void sqlcipher_sqlite3VdbeMakeReady(
}
}
- p->pVList = pParse->pVList;
- pParse->pVList = 0;
if( db->mallocFailed ){
p->nVar = 0;
p->nCursor = 0;
@@ -85165,24 +83647,17 @@ SQLITE_PRIVATE void sqlcipher_sqlite3VdbeMakeReady(
** happens to hold.
*/
SQLITE_PRIVATE void sqlcipher_sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){
- if( pCx==0 ){
- return;
- }
- assert( pCx->pBtx==0 || pCx->eCurType==CURTYPE_BTREE );
+ if( pCx ) sqlcipher_sqlite3VdbeFreeCursorNN(p,pCx);
+}
+SQLITE_PRIVATE void sqlcipher_sqlite3VdbeFreeCursorNN(Vdbe *p, VdbeCursor *pCx){
switch( pCx->eCurType ){
case CURTYPE_SORTER: {
sqlcipher_sqlite3VdbeSorterClose(p->db, pCx);
break;
}
case CURTYPE_BTREE: {
- if( pCx->isEphemeral ){
- if( pCx->pBtx ) sqlcipher_sqlite3BtreeClose(pCx->pBtx);
- /* The pCx->pCursor will be close automatically, if it exists, by
- ** the call above. */
- }else{
- assert( pCx->uc.pCursor!=0 );
- sqlcipher_sqlite3BtreeCloseCursor(pCx->uc.pCursor);
- }
+ assert( pCx->uc.pCursor!=0 );
+ sqlcipher_sqlite3BtreeCloseCursor(pCx->uc.pCursor);
break;
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -85202,14 +83677,12 @@ SQLITE_PRIVATE void sqlcipher_sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){
** Close all cursors in the current frame.
*/
static void closeCursorsInFrame(Vdbe *p){
- if( p->apCsr ){
- int i;
- for(i=0; i<p->nCursor; i++){
- VdbeCursor *pC = p->apCsr[i];
- if( pC ){
- sqlcipher_sqlite3VdbeFreeCursor(p, pC);
- p->apCsr[i] = 0;
- }
+ int i;
+ for(i=0; i<p->nCursor; i++){
+ VdbeCursor *pC = p->apCsr[i];
+ if( pC ){
+ sqlcipher_sqlite3VdbeFreeCursorNN(p, pC);
+ p->apCsr[i] = 0;
}
}
}
@@ -85258,9 +83731,7 @@ static void closeAllCursors(Vdbe *p){
}
assert( p->nFrame==0 );
closeCursorsInFrame(p);
- if( p->aMem ){
- releaseMemArray(p->aMem, p->nMem);
- }
+ releaseMemArray(p->aMem, p->nMem);
while( p->pDelFrame ){
VdbeFrame *pDel = p->pDelFrame;
p->pDelFrame = pDel->pParent;
@@ -85700,7 +84171,8 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VdbeCheckFk(Vdbe *p, int deferred){
p->rc = SQLITE_CONSTRAINT_FOREIGNKEY;
p->errorAction = OE_Abort;
sqlcipher_sqlite3VdbeError(p, "FOREIGN KEY constraint failed");
- return SQLITE_ERROR;
+ if( (p->prepFlags & SQLITE_PREPARE_SAVESQL)==0 ) return SQLITE_ERROR;
+ return SQLITE_CONSTRAINT_FOREIGNKEY;
}
return SQLITE_OK;
}
@@ -85711,9 +84183,9 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VdbeCheckFk(Vdbe *p, int deferred){
** has made changes and is in autocommit mode, then commit those
** changes. If a rollback is needed, then do the rollback.
**
-** This routine is the only way to move the state of a VM from
-** SQLITE_MAGIC_RUN to SQLITE_MAGIC_HALT. It is harmless to
-** call this on a VM that is in the SQLITE_MAGIC_HALT state.
+** This routine is the only way to move the sqlcipher_sqlite3eOpenState of a VM from
+** SQLITE_STATE_RUN to SQLITE_STATE_HALT. It is harmless to
+** call this on a VM that is in the SQLITE_STATE_HALT state.
**
** Return an error code. If the commit could not complete because of
** lock contention, return SQLITE_BUSY. If SQLITE_BUSY is returned, it
@@ -85739,9 +84211,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VdbeHalt(Vdbe *p){
** one, or the complete transaction if there is no statement transaction.
*/
- if( p->magic!=VDBE_MAGIC_RUN ){
- return SQLITE_OK;
- }
+ assert( p->eVdbeState==VDBE_RUN_STATE );
if( db->mallocFailed ){
p->rc = SQLITE_NOMEM_BKPT;
}
@@ -85750,7 +84220,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VdbeHalt(Vdbe *p){
/* 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 ){
+ if( p->bIsReader ){
int mrc; /* Primary error code from p->rc */
int eStatementOp = 0;
int isSpecialError; /* Set to true if a 'special' error */
@@ -85759,9 +84229,15 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VdbeHalt(Vdbe *p){
sqlcipher_sqlite3VdbeEnter(p);
/* Check for one of the special errors */
- mrc = p->rc & 0xff;
- isSpecialError = mrc==SQLITE_NOMEM || mrc==SQLITE_IOERR
- || mrc==SQLITE_INTERRUPT || mrc==SQLITE_FULL;
+ if( p->rc ){
+ mrc = p->rc & 0xff;
+ isSpecialError = mrc==SQLITE_NOMEM
+ || mrc==SQLITE_IOERR
+ || mrc==SQLITE_INTERRUPT
+ || mrc==SQLITE_FULL;
+ }else{
+ mrc = isSpecialError = 0;
+ }
if( isSpecialError ){
/* If the query was read-only and the error code is SQLITE_INTERRUPT,
** no rollback is necessary. Otherwise, at least a savepoint
@@ -85813,6 +84289,9 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VdbeHalt(Vdbe *p){
return SQLITE_ERROR;
}
rc = SQLITE_CONSTRAINT_FOREIGNKEY;
+ }else if( db->flags & SQLITE_CorruptRdOnly ){
+ rc = SQLITE_CORRUPT;
+ db->flags &= ~SQLITE_CorruptRdOnly;
}else{
/* The auto-commit flag is true, the vdbe program was successful
** or hit an 'OR FAIL' constraint and there are no deferred foreign
@@ -85889,15 +84368,13 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VdbeHalt(Vdbe *p){
}
/* We have successfully halted and closed the VM. Record this fact. */
- if( p->pc>=0 ){
- 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;
+ 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->eVdbeState = VDBE_HALT_STATE;
checkActiveVdbeCnt(db);
if( db->mallocFailed ){
p->rc = SQLITE_NOMEM_BKPT;
@@ -85946,6 +84423,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VdbeTransferError(Vdbe *p){
sqlcipher_sqlite3ValueSetNull(db->pErr);
}
db->errCode = rc;
+ db->errByteOffset = -1;
return rc;
}
@@ -85978,8 +84456,8 @@ static void vdbeInvokeSqllog(Vdbe *v){
** again.
**
** To look at it another way, this routine resets the state of the
-** virtual machine from VDBE_MAGIC_RUN or VDBE_MAGIC_HALT back to
-** VDBE_MAGIC_INIT.
+** virtual machine from VDBE_RUN_STATE or VDBE_HALT_STATE back to
+** VDBE_READY_STATE.
*/
SQLITE_PRIVATE int sqlcipher_sqlite3VdbeReset(Vdbe *p){
#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
@@ -85993,7 +84471,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VdbeReset(Vdbe *p){
** error, then it might not have been halted properly. So halt
** it now.
*/
- sqlcipher_sqlite3VdbeHalt(p);
+ if( p->eVdbeState==VDBE_RUN_STATE ) sqlcipher_sqlite3VdbeHalt(p);
/* If the VDBE has been run even partially, then transfer the error code
** and error message from the VDBE into the main database structure. But
@@ -86007,13 +84485,6 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VdbeReset(Vdbe *p){
}else{
db->errCode = p->rc;
}
- if( p->runOnlyOnce ) p->expired = 1;
- }else if( p->rc && p->expired ){
- /* The expired flag was set on the VDBE before the first call
- ** to sqlcipher_sqlite3_step(). For consistency (since sqlcipher_sqlite3_step() was
- ** called), set the database error in this case as well.
- */
- sqlcipher_sqlite3ErrorWithMsg(db, p->rc, p->zErrMsg ? "%s" : 0, p->zErrMsg);
}
/* Reset register contents and reclaim error message memory.
@@ -86070,7 +84541,6 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VdbeReset(Vdbe *p){
}
}
#endif
- p->magic = VDBE_MAGIC_RESET;
return p->rc & db->errMask;
}
@@ -86080,7 +84550,10 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VdbeReset(Vdbe *p){
*/
SQLITE_PRIVATE int sqlcipher_sqlite3VdbeFinalize(Vdbe *p){
int rc = SQLITE_OK;
- if( p->magic==VDBE_MAGIC_RUN || p->magic==VDBE_MAGIC_HALT ){
+ assert( VDBE_RUN_STATE>VDBE_READY_STATE );
+ assert( VDBE_HALT_STATE>VDBE_READY_STATE );
+ assert( VDBE_INIT_STATE<VDBE_READY_STATE );
+ if( p->eVdbeState>=VDBE_READY_STATE ){
rc = sqlcipher_sqlite3VdbeReset(p);
assert( (rc & p->db->errMask)==rc );
}
@@ -86132,22 +84605,24 @@ SQLITE_PRIVATE void sqlcipher_sqlite3VdbeDeleteAuxData(sqlcipher_sqlite3 *db, Au
** VdbeDelete() also unlinks the Vdbe from the list of VMs associated with
** the database connection and frees the object itself.
*/
-SQLITE_PRIVATE void sqlcipher_sqlite3VdbeClearObject(sqlcipher_sqlite3 *db, Vdbe *p){
+static void sqlcipher_sqlite3VdbeClearObject(sqlcipher_sqlite3 *db, Vdbe *p){
SubProgram *pSub, *pNext;
assert( p->db==0 || p->db==db );
- releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
+ if( p->aColName ){
+ releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
+ sqlcipher_sqlite3DbFreeNN(db, p->aColName);
+ }
for(pSub=p->pProgram; pSub; pSub=pNext){
pNext = pSub->pNext;
vdbeFreeOpArray(db, pSub->aOp, pSub->nOp);
sqlcipher_sqlite3DbFree(db, pSub);
}
- if( p->magic!=VDBE_MAGIC_INIT ){
+ if( p->eVdbeState!=VDBE_INIT_STATE ){
releaseMemArray(p->aVar, p->nVar);
- sqlcipher_sqlite3DbFree(db, p->pVList);
- sqlcipher_sqlite3DbFree(db, p->pFree);
+ if( p->pVList ) sqlcipher_sqlite3DbFreeNN(db, p->pVList);
+ if( p->pFree ) sqlcipher_sqlite3DbFreeNN(db, p->pFree);
}
vdbeFreeOpArray(db, p->aOp, p->nOp);
- sqlcipher_sqlite3DbFree(db, p->aColName);
sqlcipher_sqlite3DbFree(db, p->zSql);
#ifdef SQLITE_ENABLE_NORMALIZE
sqlcipher_sqlite3DbFree(db, p->zNormSql);
@@ -86180,17 +84655,17 @@ SQLITE_PRIVATE void sqlcipher_sqlite3VdbeDelete(Vdbe *p){
db = p->db;
assert( sqlcipher_sqlite3_mutex_held(db->mutex) );
sqlcipher_sqlite3VdbeClearObject(db, p);
- if( p->pPrev ){
- p->pPrev->pNext = p->pNext;
- }else{
- assert( db->pVdbe==p );
- db->pVdbe = p->pNext;
- }
- if( p->pNext ){
- p->pNext->pPrev = p->pPrev;
+ if( db->pnBytesFreed==0 ){
+ if( p->pPrev ){
+ p->pPrev->pNext = p->pNext;
+ }else{
+ assert( db->pVdbe==p );
+ db->pVdbe = p->pNext;
+ }
+ if( p->pNext ){
+ p->pNext->pPrev = p->pPrev;
+ }
}
- p->magic = VDBE_MAGIC_DEAD;
- p->db = 0;
sqlcipher_sqlite3DbFreeNN(db, p);
}
@@ -86207,7 +84682,7 @@ SQLITE_PRIVATE int SQLITE_NOINLINE sqlcipher_sqlite3VdbeFinishMoveto(VdbeCursor
assert( p->deferredMoveto );
assert( p->isTable );
assert( p->eCurType==CURTYPE_BTREE );
- rc = sqlcipher_sqlite3BtreeMovetoUnpacked(p->uc.pCursor, 0, p->movetoTarget, 0, &res);
+ rc = sqlcipher_sqlite3BtreeTableMoveto(p->uc.pCursor, p->movetoTarget, 0, &res);
if( rc ) return rc;
if( res!=0 ) return SQLITE_CORRUPT_BKPT;
#ifdef SQLITE_TEST
@@ -86225,7 +84700,7 @@ SQLITE_PRIVATE int SQLITE_NOINLINE sqlcipher_sqlite3VdbeFinishMoveto(VdbeCursor
** is supposed to be pointing. If the row was deleted out from under the
** cursor, set the cursor to point to a NULL row.
*/
-static int SQLITE_NOINLINE handleMovedCursor(VdbeCursor *p){
+SQLITE_PRIVATE int SQLITE_NOINLINE sqlcipher_sqlite3VdbeHandleMovedCursor(VdbeCursor *p){
int isDifferentRow, rc;
assert( p->eCurType==CURTYPE_BTREE );
assert( p->uc.pCursor!=0 );
@@ -86241,40 +84716,9 @@ static int SQLITE_NOINLINE handleMovedCursor(VdbeCursor *p){
** if need be. Return any I/O error from the restore operation.
*/
SQLITE_PRIVATE int sqlcipher_sqlite3VdbeCursorRestore(VdbeCursor *p){
- assert( p->eCurType==CURTYPE_BTREE );
- if( sqlcipher_sqlite3BtreeCursorHasMoved(p->uc.pCursor) ){
- return handleMovedCursor(p);
- }
- return SQLITE_OK;
-}
-
-/*
-** Make sure the cursor p is ready to read or write the row to which it
-** was last positioned. Return an error code if an OOM fault or I/O error
-** prevents us from positioning the cursor to its correct position.
-**
-** If a MoveTo operation is pending on the given cursor, then do that
-** MoveTo now. If no move is pending, check to see if the row has been
-** deleted out from under the cursor and if it has, mark the row as
-** a NULL row.
-**
-** If the cursor is already pointing to the correct row and that row has
-** not been deleted out from under the cursor, then this routine is a no-op.
-*/
-SQLITE_PRIVATE int sqlcipher_sqlite3VdbeCursorMoveto(VdbeCursor **pp, u32 *piCol){
- VdbeCursor *p = *pp;
- assert( p->eCurType==CURTYPE_BTREE || p->eCurType==CURTYPE_PSEUDO );
- if( p->deferredMoveto ){
- u32 iMap;
- if( p->aAltMap && (iMap = p->aAltMap[1+*piCol])>0 && !p->nullRow ){
- *pp = p->pAltCursor;
- *piCol = iMap - 1;
- return SQLITE_OK;
- }
- return sqlcipher_sqlite3VdbeFinishMoveto(p);
- }
+ assert( p->eCurType==CURTYPE_BTREE || IsNullCursor(p) );
if( sqlcipher_sqlite3BtreeCursorHasMoved(p->uc.pCursor) ){
- return handleMovedCursor(p);
+ return sqlcipher_sqlite3VdbeHandleMovedCursor(p);
}
return SQLITE_OK;
}
@@ -86285,7 +84729,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VdbeCursorMoveto(VdbeCursor **pp, u32 *piCol
** sqlcipher_sqlite3VdbeSerialType()
** sqlcipher_sqlite3VdbeSerialTypeLen()
** sqlcipher_sqlite3VdbeSerialLen()
-** sqlcipher_sqlite3VdbeSerialPut()
+** sqlcipher_sqlite3VdbeSerialPut() <--- in-lined into OP_MakeRecord as of 2022-04-02
** sqlcipher_sqlite3VdbeSerialGet()
**
** encapsulate the code that serializes values for storage in SQLite
@@ -86397,7 +84841,7 @@ SQLITE_PRIVATE u32 sqlcipher_sqlite3VdbeSerialType(Mem *pMem, int file_format, u
/*
** The sizes for serial types less than 128
*/
-static const u8 sqlcipher_sqlite3SmallTypeSizes[] = {
+SQLITE_PRIVATE const u8 sqlcipher_sqlite3SmallTypeSizes[128] = {
/* 0 1 2 3 4 5 6 7 8 9 */
/* 0 */ 0, 1, 2, 3, 4, 6, 8, 8, 0, 0,
/* 10 */ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3,
@@ -86466,7 +84910,7 @@ SQLITE_PRIVATE u8 sqlcipher_sqlite3VdbeOneByteSerialTypeLen(u8 serial_type){
** so we trust him.
*/
#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT
-static u64 floatSwap(u64 in){
+SQLITE_PRIVATE u64 sqlcipher_sqlite3FloatSwap(u64 in){
union {
u64 r;
u32 i[2];
@@ -86479,59 +84923,8 @@ static u64 floatSwap(u64 in){
u.i[1] = t;
return u.r;
}
-# define swapMixedEndianFloat(X) X = floatSwap(X)
-#else
-# define swapMixedEndianFloat(X)
-#endif
-
-/*
-** Write the serialized data blob for the value stored in pMem into
-** 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[]. 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 sqlcipher_sqlite3VdbeSerialPut(u8 *buf, Mem *pMem, u32 serial_type){
- u32 len;
+#endif /* SQLITE_MIXED_ENDIAN_64BIT_FLOAT */
- /* Integer and Real */
- if( serial_type<=7 && serial_type>0 ){
- u64 v;
- u32 i;
- if( serial_type==7 ){
- assert( sizeof(v)==sizeof(pMem->u.r) );
- memcpy(&v, &pMem->u.r, sizeof(v));
- swapMixedEndianFloat(v);
- }else{
- v = pMem->u.i;
- }
- len = i = sqlcipher_sqlite3SmallTypeSizes[serial_type];
- assert( i>0 );
- do{
- buf[--i] = (u8)(v&0xFF);
- v >>= 8;
- }while( i );
- return len;
- }
-
- /* String or blob */
- if( serial_type>=12 ){
- assert( pMem->n + ((pMem->flags & MEM_Zero)?pMem->u.nZero:0)
- == (int)sqlcipher_sqlite3VdbeSerialTypeLen(serial_type) );
- len = pMem->n;
- if( len>0 ) memcpy(buf, pMem->z, len);
- return len;
- }
-
- /* NULL or constants 0 or 1 */
- return 0;
-}
/* Input "x" is a sequence of unsigned characters that represent a
** big-endian integer. Return the equivalent native integer
@@ -86544,14 +84937,14 @@ SQLITE_PRIVATE u32 sqlcipher_sqlite3VdbeSerialPut(u8 *buf, Mem *pMem, u32 serial
/*
** 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.
+** and store the result in pMem.
**
** This function is implemented as two separate routines for performance.
** The few cases that require local variables are broken out into a separate
** routine so that in most cases the overhead of moving the stack pointer
** is avoided.
*/
-static u32 serialGet(
+static void serialGet(
const unsigned char *buf, /* Buffer to deserialize from */
u32 serial_type, /* Serial type to deserialize */
Mem *pMem /* Memory cell to write value into */
@@ -86585,9 +84978,8 @@ static u32 serialGet(
memcpy(&pMem->u.r, &x, sizeof(x));
pMem->flags = IsNaN(x) ? MEM_Null : MEM_Real;
}
- return 8;
}
-SQLITE_PRIVATE u32 sqlcipher_sqlite3VdbeSerialGet(
+SQLITE_PRIVATE void sqlcipher_sqlite3VdbeSerialGet(
const unsigned char *buf, /* Buffer to deserialize from */
u32 serial_type, /* Serial type to deserialize */
Mem *pMem /* Memory cell to write value into */
@@ -86598,13 +84990,13 @@ SQLITE_PRIVATE u32 sqlcipher_sqlite3VdbeSerialGet(
pMem->flags = MEM_Null|MEM_Zero;
pMem->n = 0;
pMem->u.nZero = 0;
- break;
+ return;
}
case 11: /* Reserved for future use */
case 0: { /* Null */
/* EVIDENCE-OF: R-24078-09375 Value is a NULL. */
pMem->flags = MEM_Null;
- break;
+ return;
}
case 1: {
/* EVIDENCE-OF: R-44885-25196 Value is an 8-bit twos-complement
@@ -86612,7 +85004,7 @@ SQLITE_PRIVATE u32 sqlcipher_sqlite3VdbeSerialGet(
pMem->u.i = ONE_BYTE_INT(buf);
pMem->flags = MEM_Int;
testcase( pMem->u.i<0 );
- return 1;
+ return;
}
case 2: { /* 2-byte signed integer */
/* EVIDENCE-OF: R-49794-35026 Value is a big-endian 16-bit
@@ -86620,7 +85012,7 @@ SQLITE_PRIVATE u32 sqlcipher_sqlite3VdbeSerialGet(
pMem->u.i = TWO_BYTE_INT(buf);
pMem->flags = MEM_Int;
testcase( pMem->u.i<0 );
- return 2;
+ return;
}
case 3: { /* 3-byte signed integer */
/* EVIDENCE-OF: R-37839-54301 Value is a big-endian 24-bit
@@ -86628,7 +85020,7 @@ SQLITE_PRIVATE u32 sqlcipher_sqlite3VdbeSerialGet(
pMem->u.i = THREE_BYTE_INT(buf);
pMem->flags = MEM_Int;
testcase( pMem->u.i<0 );
- return 3;
+ return;
}
case 4: { /* 4-byte signed integer */
/* EVIDENCE-OF: R-01849-26079 Value is a big-endian 32-bit
@@ -86640,7 +85032,7 @@ SQLITE_PRIVATE u32 sqlcipher_sqlite3VdbeSerialGet(
#endif
pMem->flags = MEM_Int;
testcase( pMem->u.i<0 );
- return 4;
+ return;
}
case 5: { /* 6-byte signed integer */
/* EVIDENCE-OF: R-50385-09674 Value is a big-endian 48-bit
@@ -86648,13 +85040,14 @@ SQLITE_PRIVATE u32 sqlcipher_sqlite3VdbeSerialGet(
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;
+ return;
}
case 6: /* 8-byte signed integer */
case 7: { /* IEEE floating point */
/* These use local variables, so do them in a separate routine
** to avoid having to move the frame pointer in the common case */
- return serialGet(buf,serial_type,pMem);
+ serialGet(buf,serial_type,pMem);
+ return;
}
case 8: /* Integer 0 */
case 9: { /* Integer 1 */
@@ -86662,7 +85055,7 @@ SQLITE_PRIVATE u32 sqlcipher_sqlite3VdbeSerialGet(
/* EVIDENCE-OF: R-18143-12121 Value is the integer 1. */
pMem->u.i = serial_type-8;
pMem->flags = MEM_Int;
- return 0;
+ return;
}
default: {
/* EVIDENCE-OF: R-14606-31564 Value is a BLOB that is (N-12)/2 bytes in
@@ -86673,10 +85066,10 @@ SQLITE_PRIVATE u32 sqlcipher_sqlite3VdbeSerialGet(
pMem->z = (char *)buf;
pMem->n = (serial_type-12)/2;
pMem->flags = aFlag[serial_type&1];
- return pMem->n;
+ return;
}
}
- return 0;
+ return;
}
/*
** This routine is used to allocate sufficient space for an UnpackedRecord
@@ -86697,10 +85090,10 @@ SQLITE_PRIVATE UnpackedRecord *sqlcipher_sqlite3VdbeAllocUnpackedRecord(
){
UnpackedRecord *p; /* Unpacked record to return */
int nByte; /* Number of bytes required for *p */
- nByte = ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*(pKeyInfo->nKeyField+1);
+ nByte = ROUND8P(sizeof(UnpackedRecord)) + sizeof(Mem)*(pKeyInfo->nKeyField+1);
p = (UnpackedRecord *)sqlcipher_sqlite3DbMallocRaw(pKeyInfo->db, nByte);
if( !p ) return 0;
- p->aMem = (Mem*)&((char*)p)[ROUND8(sizeof(UnpackedRecord))];
+ p->aMem = (Mem*)&((char*)p)[ROUND8P(sizeof(UnpackedRecord))];
assert( pKeyInfo->aSortFlags!=0 );
p->pKeyInfo = pKeyInfo;
p->nField = pKeyInfo->nKeyField + 1;
@@ -86739,7 +85132,8 @@ SQLITE_PRIVATE void sqlcipher_sqlite3VdbeRecordUnpack(
/* pMem->flags = 0; // sqlcipher_sqlite3VdbeSerialGet() will set this for us */
pMem->szMalloc = 0;
pMem->z = 0;
- d += sqlcipher_sqlite3VdbeSerialGet(&aKey[d], serial_type, pMem);
+ sqlcipher_sqlite3VdbeSerialGet(&aKey[d], serial_type, pMem);
+ d += sqlcipher_sqlite3VdbeSerialTypeLen(serial_type);
pMem++;
if( (++u)>=p->nField ) break;
}
@@ -86823,7 +85217,8 @@ static int vdbeRecordCompareDebug(
/* Extract the values to be compared.
*/
- d1 += sqlcipher_sqlite3VdbeSerialGet(&aKey1[d1], serial_type1, &mem1);
+ sqlcipher_sqlite3VdbeSerialGet(&aKey1[d1], serial_type1, &mem1);
+ d1 += sqlcipher_sqlite3VdbeSerialTypeLen(serial_type1);
/* Do the comparison
*/
@@ -86934,8 +85329,8 @@ static int vdbeCompareMemString(
}else{
rc = pColl->xCmp(pColl->pUser, c1.n, v1, c2.n, v2);
}
- sqlcipher_sqlite3VdbeMemRelease(&c1);
- sqlcipher_sqlite3VdbeMemRelease(&c2);
+ sqlcipher_sqlite3VdbeMemReleaseMalloc(&c1);
+ sqlcipher_sqlite3VdbeMemReleaseMalloc(&c2);
return rc;
}
}
@@ -86990,7 +85385,7 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlcipher_sqlite3BlobCompare(const Mem *pB1,
** number. Return negative, zero, or positive if the first (i64) is less than,
** equal to, or greater than the second (double).
*/
-static int sqlcipher_sqlite3IntFloatCompare(i64 i, double r){
+SQLITE_PRIVATE int sqlcipher_sqlite3IntFloatCompare(i64 i, double r){
if( sizeof(LONGDOUBLE_TYPE)>8 ){
LONGDOUBLE_TYPE x = (LONGDOUBLE_TYPE)i;
testcase( x<r );
@@ -87196,14 +85591,22 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VdbeRecordCompareWithSkip(
** 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);
+ u32 s1 = aKey1[1];
+ if( s1<0x80 ){
+ idx1 = 2;
+ }else{
+ idx1 = 1 + sqlcipher_sqlite3GetVarint32(&aKey1[1], &s1);
+ }
szHdr1 = aKey1[0];
d1 = szHdr1 + sqlcipher_sqlite3VdbeSerialTypeLen(s1);
i = 1;
pRhs++;
}else{
- idx1 = getVarint32(aKey1, szHdr1);
+ if( (szHdr1 = aKey1[0])<0x80 ){
+ idx1 = 1;
+ }else{
+ idx1 = sqlcipher_sqlite3GetVarint32(aKey1, &szHdr1);
+ }
d1 = szHdr1;
i = 0;
}
@@ -87459,7 +85862,8 @@ static int vdbeRecordCompareInt(
return sqlcipher_sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2);
}
- v = pPKey2->aMem[0].u.i;
+ assert( pPKey2->u.i == pPKey2->aMem[0].u.i );
+ v = pPKey2->u.i;
if( v>lhs ){
res = pPKey2->r1;
}else if( v<lhs ){
@@ -87494,12 +85898,18 @@ static int vdbeRecordCompareString(
int res;
assert( pPKey2->aMem[0].flags & MEM_Str );
+ assert( pPKey2->aMem[0].n == pPKey2->n );
+ assert( pPKey2->aMem[0].z == pPKey2->u.z );
vdbeAssertFieldCountWithinLimits(nKey1, pKey1, pPKey2->pKeyInfo);
- serial_type = (u8)(aKey1[1]);
- if( serial_type >= 0x80 ){
- sqlcipher_sqlite3GetVarint32(&aKey1[1], (u32*)&serial_type);
- }
+ serial_type = (signed char)(aKey1[1]);
+
+vrcs_restart:
if( serial_type<12 ){
+ if( serial_type<0 ){
+ sqlcipher_sqlite3GetVarint32(&aKey1[1], (u32*)&serial_type);
+ if( serial_type>=12 ) goto vrcs_restart;
+ assert( CORRUPT_DB );
+ }
res = pPKey2->r1; /* (pKey1/nKey1) is a number or a null */
}else if( !(serial_type & 0x01) ){
res = pPKey2->r2; /* (pKey1/nKey1) is a blob */
@@ -87513,15 +85923,15 @@ static int vdbeRecordCompareString(
pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT;
return 0; /* Corruption */
}
- nCmp = MIN( pPKey2->aMem[0].n, nStr );
- res = memcmp(&aKey1[szHdr], pPKey2->aMem[0].z, nCmp);
+ nCmp = MIN( pPKey2->n, nStr );
+ res = memcmp(&aKey1[szHdr], pPKey2->u.z, nCmp);
if( res>0 ){
res = pPKey2->r2;
}else if( res<0 ){
res = pPKey2->r1;
}else{
- res = nStr - pPKey2->aMem[0].n;
+ res = nStr - pPKey2->n;
if( res==0 ){
if( pPKey2->nField>1 ){
res = sqlcipher_sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1);
@@ -87576,6 +85986,7 @@ SQLITE_PRIVATE RecordCompare sqlcipher_sqlite3VdbeFindCompare(UnpackedRecord *p)
p->r2 = 1;
}
if( (flags & MEM_Int) ){
+ p->u.i = p->aMem[0].u.i;
return vdbeRecordCompareInt;
}
testcase( flags & MEM_Real );
@@ -87585,6 +85996,8 @@ SQLITE_PRIVATE RecordCompare sqlcipher_sqlite3VdbeFindCompare(UnpackedRecord *p)
&& p->pKeyInfo->aColl[0]==0
){
assert( flags & MEM_Str );
+ p->u.z = p->aMem[0].z;
+ p->n = p->aMem[0].n;
return vdbeRecordCompareString;
}
}
@@ -87627,7 +86040,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VdbeIdxRowid(sqlcipher_sqlite3 *db, BtCursor
/* The index entry must begin with a header size */
getVarint32NR((u8*)m.z, szHdr);
testcase( szHdr==3 );
- testcase( szHdr==m.n );
+ testcase( szHdr==(u32)m.n );
testcase( szHdr>0x7fffffff );
assert( m.n>=0 );
if( unlikely(szHdr<3 || szHdr>(unsigned)m.n) ){
@@ -87657,14 +86070,14 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VdbeIdxRowid(sqlcipher_sqlite3 *db, BtCursor
/* Fetch the integer off the end of the index record */
sqlcipher_sqlite3VdbeSerialGet((u8*)&m.z[m.n-lenRowid], typeRowid, &v);
*rowid = v.u.i;
- sqlcipher_sqlite3VdbeMemRelease(&m);
+ sqlcipher_sqlite3VdbeMemReleaseMalloc(&m);
return SQLITE_OK;
/* Jump here if database corruption is detected after m has been
** allocated. Free the m object and return SQLITE_CORRUPT. */
idx_rowid_corruption:
testcase( m.szMalloc!=0 );
- sqlcipher_sqlite3VdbeMemRelease(&m);
+ sqlcipher_sqlite3VdbeMemReleaseMalloc(&m);
return SQLITE_CORRUPT_BKPT;
}
@@ -87706,7 +86119,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VdbeIdxKeyCompare(
return rc;
}
*res = sqlcipher_sqlite3VdbeRecordCompareWithSkip(m.n, m.z, pUnpacked, 0);
- sqlcipher_sqlite3VdbeMemRelease(&m);
+ sqlcipher_sqlite3VdbeMemReleaseMalloc(&m);
return SQLITE_OK;
}
@@ -87714,7 +86127,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VdbeIdxKeyCompare(
** This routine sets the value to be returned by subsequent calls to
** sqlcipher_sqlite3_changes() on the database handle 'db'.
*/
-SQLITE_PRIVATE void sqlcipher_sqlite3VdbeSetChanges(sqlcipher_sqlite3 *db, int nChange){
+SQLITE_PRIVATE void sqlcipher_sqlite3VdbeSetChanges(sqlcipher_sqlite3 *db, i64 nChange){
assert( sqlcipher_sqlite3_mutex_held(db->mutex) );
db->nChange = nChange;
db->nTotalChange += nChange;
@@ -87873,7 +86286,7 @@ static void vdbeFreeUnpacked(sqlcipher_sqlite3 *db, int nField, UnpackedRecord *
int i;
for(i=0; i<nField; i++){
Mem *pMem = &p->aMem[i];
- if( pMem->zMalloc ) sqlcipher_sqlite3VdbeMemRelease(pMem);
+ if( pMem->zMalloc ) sqlcipher_sqlite3VdbeMemReleaseMalloc(pMem);
}
sqlcipher_sqlite3DbFreeNN(db, p);
}
@@ -87894,7 +86307,8 @@ SQLITE_PRIVATE void sqlcipher_sqlite3VdbePreUpdateHook(
const char *zDb, /* Database name */
Table *pTab, /* Modified table */
i64 iKey1, /* Initial key value */
- int iReg /* Register for new.* record */
+ int iReg, /* Register for new.* record */
+ int iBlobWrite
){
sqlcipher_sqlite3 *db = v->db;
i64 iKey2;
@@ -87915,6 +86329,8 @@ SQLITE_PRIVATE void sqlcipher_sqlite3VdbePreUpdateHook(
}
}
+ assert( pCsr!=0 );
+ assert( pCsr->eCurType==CURTYPE_BTREE );
assert( pCsr->nField==pTab->nCol
|| (pCsr->nField==pTab->nCol+1 && op==SQLITE_DELETE && iReg==-1)
);
@@ -87930,6 +86346,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3VdbePreUpdateHook(
preupdate.iKey1 = iKey1;
preupdate.iKey2 = iKey2;
preupdate.pTab = pTab;
+ preupdate.iBlobWrite = iBlobWrite;
db->pPreUpdate = &preupdate;
db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2);
@@ -88296,6 +86713,9 @@ SQLITE_API sqlcipher_sqlite3_value *sqlcipher_sqlite3_value_dup(const sqlcipher_
sqlcipher_sqlite3ValueFree(pNew);
pNew = 0;
}
+ }else if( pNew->flags & MEM_Null ){
+ /* Do not duplicate pointer values */
+ pNew->flags &= ~(MEM_Term|MEM_Subtype);
}
return pNew;
}
@@ -88313,8 +86733,8 @@ SQLITE_API void sqlcipher_sqlite3_value_free(sqlcipher_sqlite3_value *pOld){
** the function result.
**
** The setStrOrError() function calls sqlcipher_sqlite3VdbeMemSetStr() to store the
-** result as a string or blob but if the string or blob is too large, it
-** then sets the error code to SQLITE_TOOBIG
+** result as a string or blob. Appropriate errors are set if the string/blob
+** is too big or if an OOM occurs.
**
** The invokeValueDestructor(P,X) routine invokes destructor function X()
** on value P is not going to be used and need to be destroyed.
@@ -88326,7 +86746,21 @@ static void setResultStrOrError(
u8 enc, /* Encoding of z. 0 for BLOBs */
void (*xDel)(void*) /* Destructor function */
){
- if( sqlcipher_sqlite3VdbeMemSetStr(pCtx->pOut, z, n, enc, xDel)==SQLITE_TOOBIG ){
+ Mem *pOut = pCtx->pOut;
+ int rc = sqlcipher_sqlite3VdbeMemSetStr(pOut, z, n, enc, xDel);
+ if( rc ){
+ if( rc==SQLITE_TOOBIG ){
+ sqlcipher_sqlite3_result_error_toobig(pCtx);
+ }else{
+ /* The only errors possible from sqlcipher_sqlite3VdbeMemSetStr are
+ ** SQLITE_TOOBIG and SQLITE_NOMEM */
+ assert( rc==SQLITE_NOMEM );
+ sqlcipher_sqlite3_result_error_nomem(pCtx);
+ }
+ return;
+ }
+ sqlcipher_sqlite3VdbeChangeEncoding(pOut, pCtx->enc);
+ if( sqlcipher_sqlite3VdbeMemTooBig(pOut) ){
sqlcipher_sqlite3_result_error_toobig(pCtx);
}
}
@@ -88343,7 +86777,7 @@ static int invokeValueDestructor(
}else{
xDel((void*)p);
}
- if( pCtx ) sqlcipher_sqlite3_result_error_toobig(pCtx);
+ sqlcipher_sqlite3_result_error_toobig(pCtx);
return SQLITE_TOOBIG;
}
SQLITE_API void sqlcipher_sqlite3_result_blob(
@@ -88471,21 +86905,30 @@ SQLITE_API void sqlcipher_sqlite3_result_text16le(
}
#endif /* SQLITE_OMIT_UTF16 */
SQLITE_API void sqlcipher_sqlite3_result_value(sqlcipher_sqlite3_context *pCtx, sqlcipher_sqlite3_value *pValue){
+ Mem *pOut = pCtx->pOut;
assert( sqlcipher_sqlite3_mutex_held(pCtx->pOut->db->mutex) );
- sqlcipher_sqlite3VdbeMemCopy(pCtx->pOut, pValue);
+ sqlcipher_sqlite3VdbeMemCopy(pOut, pValue);
+ sqlcipher_sqlite3VdbeChangeEncoding(pOut, pCtx->enc);
+ if( sqlcipher_sqlite3VdbeMemTooBig(pOut) ){
+ sqlcipher_sqlite3_result_error_toobig(pCtx);
+ }
}
SQLITE_API void sqlcipher_sqlite3_result_zeroblob(sqlcipher_sqlite3_context *pCtx, int n){
- assert( sqlcipher_sqlite3_mutex_held(pCtx->pOut->db->mutex) );
- sqlcipher_sqlite3VdbeMemSetZeroBlob(pCtx->pOut, n);
+ sqlcipher_sqlite3_result_zeroblob64(pCtx, n>0 ? n : 0);
}
SQLITE_API int sqlcipher_sqlite3_result_zeroblob64(sqlcipher_sqlite3_context *pCtx, u64 n){
Mem *pOut = pCtx->pOut;
assert( sqlcipher_sqlite3_mutex_held(pOut->db->mutex) );
if( n>(u64)pOut->db->aLimit[SQLITE_LIMIT_LENGTH] ){
+ sqlcipher_sqlite3_result_error_toobig(pCtx);
return SQLITE_TOOBIG;
}
+#ifndef SQLITE_OMIT_INCRBLOB
sqlcipher_sqlite3VdbeMemSetZeroBlob(pCtx->pOut, (int)n);
return SQLITE_OK;
+#else
+ return sqlcipher_sqlite3VdbeMemSetZeroBlob(pCtx->pOut, (int)n);
+#endif
}
SQLITE_API void sqlcipher_sqlite3_result_error_code(sqlcipher_sqlite3_context *pCtx, int errCode){
pCtx->isError = errCode ? errCode : -1;
@@ -88493,8 +86936,8 @@ SQLITE_API void sqlcipher_sqlite3_result_error_code(sqlcipher_sqlite3_context *p
if( pCtx->pVdbe ) pCtx->pVdbe->rcApp = errCode;
#endif
if( pCtx->pOut->flags & MEM_Null ){
- sqlcipher_sqlite3VdbeMemSetStr(pCtx->pOut, sqlcipher_sqlite3ErrStr(errCode), -1,
- SQLITE_UTF8, SQLITE_STATIC);
+ setResultStrOrError(pCtx, sqlcipher_sqlite3ErrStr(errCode), -1, SQLITE_UTF8,
+ SQLITE_STATIC);
}
}
@@ -88568,80 +87011,83 @@ static int sqlcipher_sqlite3Step(Vdbe *p){
int rc;
assert(p);
- if( p->magic!=VDBE_MAGIC_RUN ){
- /* We used to require that sqlcipher_sqlite3_reset() be called before retrying
- ** sqlcipher_sqlite3_step() after any error or after SQLITE_DONE. But beginning
- ** with version 3.7.0, we changed this so that sqlcipher_sqlite3_reset() would
- ** be called automatically instead of throwing the SQLITE_MISUSE error.
- ** This "automatic-reset" change is not technically an incompatibility,
- ** since any application that receives an SQLITE_MISUSE is broken by
- ** definition.
- **
- ** Nevertheless, some published applications that were originally written
- ** for version 3.6.23 or earlier do in fact depend on SQLITE_MISUSE
- ** returns, and those were broken by the automatic-reset change. As a
- ** a work-around, the SQLITE_OMIT_AUTORESET compile-time restores the
- ** legacy behavior of returning SQLITE_MISUSE for cases where the
- ** previous sqlcipher_sqlite3_step() returned something other than a SQLITE_LOCKED
- ** or SQLITE_BUSY error.
- */
-#ifdef SQLITE_OMIT_AUTORESET
- if( (rc = p->rc&0xff)==SQLITE_BUSY || rc==SQLITE_LOCKED ){
- sqlcipher_sqlite3_reset((sqlcipher_sqlite3_stmt*)p);
- }else{
- return SQLITE_MISUSE_BKPT;
- }
-#else
- sqlcipher_sqlite3_reset((sqlcipher_sqlite3_stmt*)p);
-#endif
- }
-
- /* Check that malloc() has not failed. If it has, return early. */
db = p->db;
- if( db->mallocFailed ){
- p->rc = SQLITE_NOMEM;
- return SQLITE_NOMEM_BKPT;
- }
+ if( p->eVdbeState!=VDBE_RUN_STATE ){
+ restart_step:
+ if( p->eVdbeState==VDBE_READY_STATE ){
+ if( p->expired ){
+ p->rc = SQLITE_SCHEMA;
+ rc = SQLITE_ERROR;
+ if( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 ){
+ /* If this statement was prepared using saved SQL and an
+ ** error has occurred, then return the error code in p->rc to the
+ ** caller. Set the error code in the database handle to the same
+ ** value.
+ */
+ rc = sqlcipher_sqlite3VdbeTransferError(p);
+ }
+ goto end_of_step;
+ }
- if( p->pc<0 && p->expired ){
- p->rc = SQLITE_SCHEMA;
- rc = SQLITE_ERROR;
- if( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0 ){
- /* If this statement was prepared using saved SQL and an
- ** error has occurred, then return the error code in p->rc to the
- ** caller. Set the error code in the database handle to the same value.
+ /* If there are no other statements currently running, then
+ ** reset the interrupt flag. This prevents a call to sqlcipher_sqlite3_interrupt
+ ** from interrupting a statement that has not yet started.
*/
- rc = sqlcipher_sqlite3VdbeTransferError(p);
- }
- goto end_of_step;
- }
- if( p->pc<0 ){
- /* If there are no other statements currently running, then
- ** reset the interrupt flag. This prevents a call to sqlcipher_sqlite3_interrupt
- ** from interrupting a statement that has not yet started.
- */
- if( db->nVdbeActive==0 ){
- AtomicStore(&db->u1.isInterrupted, 0);
- }
+ if( db->nVdbeActive==0 ){
+ AtomicStore(&db->u1.isInterrupted, 0);
+ }
- assert( db->nVdbeWrite>0 || db->autoCommit==0
- || (db->nDeferredCons==0 && db->nDeferredImmCons==0)
- );
+ assert( db->nVdbeWrite>0 || db->autoCommit==0
+ || (db->nDeferredCons==0 && db->nDeferredImmCons==0)
+ );
#ifndef SQLITE_OMIT_TRACE
- if( (db->mTrace & (SQLITE_TRACE_PROFILE|SQLITE_TRACE_XPROFILE))!=0
- && !db->init.busy && p->zSql ){
- sqlcipher_sqlite3OsCurrentTimeInt64(db->pVfs, &p->startTime);
- }else{
- assert( p->startTime==0 );
- }
+ if( (db->mTrace & (SQLITE_TRACE_PROFILE|SQLITE_TRACE_XPROFILE))!=0
+ && !db->init.busy && p->zSql ){
+ sqlcipher_sqlite3OsCurrentTimeInt64(db->pVfs, &p->startTime);
+ }else{
+ assert( p->startTime==0 );
+ }
#endif
- db->nVdbeActive++;
- if( p->readOnly==0 ) db->nVdbeWrite++;
- if( p->bIsReader ) db->nVdbeRead++;
- p->pc = 0;
+ db->nVdbeActive++;
+ if( p->readOnly==0 ) db->nVdbeWrite++;
+ if( p->bIsReader ) db->nVdbeRead++;
+ p->pc = 0;
+ p->eVdbeState = VDBE_RUN_STATE;
+ }else
+
+ if( ALWAYS(p->eVdbeState==VDBE_HALT_STATE) ){
+ /* We used to require that sqlcipher_sqlite3_reset() be called before retrying
+ ** sqlcipher_sqlite3_step() after any error or after SQLITE_DONE. But beginning
+ ** with version 3.7.0, we changed this so that sqlcipher_sqlite3_reset() would
+ ** be called automatically instead of throwing the SQLITE_MISUSE error.
+ ** This "automatic-reset" change is not technically an incompatibility,
+ ** since any application that receives an SQLITE_MISUSE is broken by
+ ** definition.
+ **
+ ** Nevertheless, some published applications that were originally written
+ ** for version 3.6.23 or earlier do in fact depend on SQLITE_MISUSE
+ ** returns, and those were broken by the automatic-reset change. As a
+ ** a work-around, the SQLITE_OMIT_AUTORESET compile-time restores the
+ ** legacy behavior of returning SQLITE_MISUSE for cases where the
+ ** previous sqlcipher_sqlite3_step() returned something other than a SQLITE_LOCKED
+ ** or SQLITE_BUSY error.
+ */
+#ifdef SQLITE_OMIT_AUTORESET
+ if( (rc = p->rc&0xff)==SQLITE_BUSY || rc==SQLITE_LOCKED ){
+ sqlcipher_sqlite3_reset((sqlcipher_sqlite3_stmt*)p);
+ }else{
+ return SQLITE_MISUSE_BKPT;
+ }
+#else
+ sqlcipher_sqlite3_reset((sqlcipher_sqlite3_stmt*)p);
+#endif
+ assert( p->eVdbeState==VDBE_READY_STATE );
+ goto restart_step;
+ }
}
+
#ifdef SQLITE_DEBUG
p->rcApp = SQLITE_OK;
#endif
@@ -88656,7 +87102,12 @@ static int sqlcipher_sqlite3Step(Vdbe *p){
db->nVdbeExec--;
}
- if( rc!=SQLITE_ROW ){
+ if( rc==SQLITE_ROW ){
+ assert( p->rc==SQLITE_OK );
+ assert( db->mallocFailed==0 );
+ db->errCode = SQLITE_ROW;
+ return SQLITE_ROW;
+ }else{
#ifndef SQLITE_OMIT_TRACE
/* If the statement completed successfully, invoke the profile callback */
checkProfileCallback(db, p);
@@ -88708,7 +87159,6 @@ SQLITE_API int sqlcipher_sqlite3_step(sqlcipher_sqlite3_stmt *pStmt){
}
db = v->db;
sqlcipher_sqlite3_mutex_enter(db->mutex);
- v->doingRerun = 0;
while( (rc = sqlcipher_sqlite3Step(v))==SQLITE_SCHEMA
&& cnt++ < SQLITE_MAX_SCHEMA_RETRY ){
int savedPc = v->pc;
@@ -88734,7 +87184,13 @@ SQLITE_API int sqlcipher_sqlite3_step(sqlcipher_sqlite3_stmt *pStmt){
break;
}
sqlcipher_sqlite3_reset(pStmt);
- if( savedPc>=0 ) v->doingRerun = 1;
+ if( savedPc>=0 ){
+ /* Setting minWriteFileFormat to 254 is a signal to the OP_Init and
+ ** OP_Trace opcodes to *not* perform SQLITE_TRACE_STMT because it has
+ ** already been done once on a prior invocation that failed due to
+ ** SQLITE_SCHEMA. tag-20220401a */
+ v->minWriteFileFormat = 254;
+ }
assert( v->expired==0 );
}
sqlcipher_sqlite3_mutex_leave(db->mutex);
@@ -88786,6 +87242,70 @@ SQLITE_API int sqlcipher_sqlite3_vtab_nochange(sqlcipher_sqlite3_context *p){
}
/*
+** Implementation of sqlcipher_sqlite3_vtab_in_first() (if bNext==0) and
+** sqlcipher_sqlite3_vtab_in_next() (if bNext!=0).
+*/
+static int valueFromValueList(
+ sqlcipher_sqlite3_value *pVal, /* Pointer to the ValueList object */
+ sqlcipher_sqlite3_value **ppOut, /* Store the next value from the list here */
+ int bNext /* 1 for _next(). 0 for _first() */
+){
+ int rc;
+ ValueList *pRhs;
+
+ *ppOut = 0;
+ if( pVal==0 ) return SQLITE_MISUSE;
+ pRhs = (ValueList*)sqlcipher_sqlite3_value_pointer(pVal, "ValueList");
+ if( pRhs==0 ) return SQLITE_MISUSE;
+ if( bNext ){
+ rc = sqlcipher_sqlite3BtreeNext(pRhs->pCsr, 0);
+ }else{
+ int dummy = 0;
+ rc = sqlcipher_sqlite3BtreeFirst(pRhs->pCsr, &dummy);
+ assert( rc==SQLITE_OK || sqlcipher_sqlite3BtreeEof(pRhs->pCsr) );
+ if( sqlcipher_sqlite3BtreeEof(pRhs->pCsr) ) rc = SQLITE_DONE;
+ }
+ if( rc==SQLITE_OK ){
+ u32 sz; /* Size of current row in bytes */
+ Mem sMem; /* Raw content of current row */
+ memset(&sMem, 0, sizeof(sMem));
+ sz = sqlcipher_sqlite3BtreePayloadSize(pRhs->pCsr);
+ rc = sqlcipher_sqlite3VdbeMemFromBtreeZeroOffset(pRhs->pCsr,(int)sz,&sMem);
+ if( rc==SQLITE_OK ){
+ u8 *zBuf = (u8*)sMem.z;
+ u32 iSerial;
+ sqlcipher_sqlite3_value *pOut = pRhs->pOut;
+ int iOff = 1 + getVarint32(&zBuf[1], iSerial);
+ sqlcipher_sqlite3VdbeSerialGet(&zBuf[iOff], iSerial, pOut);
+ pOut->enc = ENC(pOut->db);
+ if( (pOut->flags & MEM_Ephem)!=0 && sqlcipher_sqlite3VdbeMemMakeWriteable(pOut) ){
+ rc = SQLITE_NOMEM;
+ }else{
+ *ppOut = pOut;
+ }
+ }
+ sqlcipher_sqlite3VdbeMemRelease(&sMem);
+ }
+ return rc;
+}
+
+/*
+** Set the iterator value pVal to point to the first value in the set.
+** Set (*ppOut) to point to this value before returning.
+*/
+SQLITE_API int sqlcipher_sqlite3_vtab_in_first(sqlcipher_sqlite3_value *pVal, sqlcipher_sqlite3_value **ppOut){
+ return valueFromValueList(pVal, ppOut, 0);
+}
+
+/*
+** Set the iterator value pVal to point to the next value in the set.
+** Set (*ppOut) to point to this value before returning.
+*/
+SQLITE_API int sqlcipher_sqlite3_vtab_in_next(sqlcipher_sqlite3_value *pVal, sqlcipher_sqlite3_value **ppOut){
+ return valueFromValueList(pVal, ppOut, 1);
+}
+
+/*
** Return the current time for a statement. If the current time
** is requested more than once within the same run of a single prepared
** statement, the exact same time is returned for each invocation regardless
@@ -88979,15 +87499,15 @@ static const Mem *columnNullValue(void){
#endif
= {
/* .u = */ {0},
+ /* .z = */ (char*)0,
+ /* .n = */ (int)0,
/* .flags = */ (u16)MEM_Null,
/* .enc = */ (u8)0,
/* .eSubtype = */ (u8)0,
- /* .n = */ (int)0,
- /* .z = */ (char*)0,
- /* .zMalloc = */ (char*)0,
+ /* .db = */ (sqlcipher_sqlite3*)0,
/* .szMalloc = */ (int)0,
/* .uTemp = */ (u32)0,
- /* .db = */ (sqlcipher_sqlite3*)0,
+ /* .zMalloc = */ (char*)0,
/* .xDel = */ (void(*)(void*))0,
#ifdef SQLITE_DEBUG
/* .pScopyFrom = */ (Mem*)0,
@@ -89284,7 +87804,7 @@ static int vdbeUnbind(Vdbe *p, int i){
return SQLITE_MISUSE_BKPT;
}
sqlcipher_sqlite3_mutex_enter(p->db->mutex);
- if( p->magic!=VDBE_MAGIC_RUN || p->pc>=0 ){
+ if( p->eVdbeState!=VDBE_READY_STATE ){
sqlcipher_sqlite3Error(p->db, SQLITE_MISUSE);
sqlcipher_sqlite3_mutex_leave(p->db->mutex);
sqlcipher_sqlite3_log(SQLITE_MISUSE,
@@ -89325,7 +87845,7 @@ static int bindText(
sqlcipher_sqlite3_stmt *pStmt, /* The statement to bind against */
int i, /* Index of the parameter to bind */
const void *zData, /* Pointer to the data to be bound */
- int nData, /* Number of bytes of data to be bound */
+ i64 nData, /* Number of bytes of data to be bound */
void (*xDel)(void*), /* Destructor for the data */
u8 encoding /* Encoding for the data */
){
@@ -89377,11 +87897,7 @@ SQLITE_API int sqlcipher_sqlite3_bind_blob64(
void (*xDel)(void*)
){
assert( xDel!=SQLITE_DYNAMIC );
- if( nData>0x7fffffff ){
- return invokeValueDestructor(zData, xDel, 0);
- }else{
- return bindText(pStmt, i, zData, (int)nData, xDel, 0);
- }
+ return bindText(pStmt, i, zData, nData, xDel, 0);
}
SQLITE_API int sqlcipher_sqlite3_bind_double(sqlcipher_sqlite3_stmt *pStmt, int i, double rValue){
int rc;
@@ -89451,12 +87967,8 @@ SQLITE_API int sqlcipher_sqlite3_bind_text64(
unsigned char enc
){
assert( xDel!=SQLITE_DYNAMIC );
- if( nData>0x7fffffff ){
- return invokeValueDestructor(zData, xDel, 0);
- }else{
- if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE;
- return bindText(pStmt, i, zData, (int)nData, xDel, enc);
- }
+ if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE;
+ return bindText(pStmt, i, zData, nData, xDel, enc);
}
#ifndef SQLITE_OMIT_UTF16
SQLITE_API int sqlcipher_sqlite3_bind_text16(
@@ -89477,7 +87989,10 @@ SQLITE_API int sqlcipher_sqlite3_bind_value(sqlcipher_sqlite3_stmt *pStmt, int i
break;
}
case SQLITE_FLOAT: {
- rc = sqlcipher_sqlite3_bind_double(pStmt, i, pValue->u.r);
+ assert( pValue->flags & (MEM_Real|MEM_IntReal) );
+ rc = sqlcipher_sqlite3_bind_double(pStmt, i,
+ (pValue->flags & MEM_Real) ? pValue->u.r : (double)pValue->u.i
+ );
break;
}
case SQLITE_BLOB: {
@@ -89505,7 +88020,11 @@ SQLITE_API int sqlcipher_sqlite3_bind_zeroblob(sqlcipher_sqlite3_stmt *pStmt, in
Vdbe *p = (Vdbe *)pStmt;
rc = vdbeUnbind(p, i);
if( rc==SQLITE_OK ){
+#ifndef SQLITE_OMIT_INCRBLOB
sqlcipher_sqlite3VdbeMemSetZeroBlob(&p->aVar[i-1], n);
+#else
+ rc = sqlcipher_sqlite3VdbeMemSetZeroBlob(&p->aVar[i-1], n);
+#endif
sqlcipher_sqlite3_mutex_leave(p->db->mutex);
}
return rc;
@@ -89638,7 +88157,7 @@ SQLITE_API int sqlcipher_sqlite3_stmt_isexplain(sqlcipher_sqlite3_stmt *pStmt){
*/
SQLITE_API int sqlcipher_sqlite3_stmt_busy(sqlcipher_sqlite3_stmt *pStmt){
Vdbe *v = (Vdbe*)pStmt;
- return v!=0 && v->magic==VDBE_MAGIC_RUN && v->pc>=0;
+ return v!=0 && v->eVdbeState==VDBE_RUN_STATE;
}
/*
@@ -89684,8 +88203,7 @@ SQLITE_API int sqlcipher_sqlite3_stmt_status(sqlcipher_sqlite3_stmt *pStmt, int
sqlcipher_sqlite3_mutex_enter(db->mutex);
v = 0;
db->pnBytesFreed = (int*)&v;
- sqlcipher_sqlite3VdbeClearObject(db, pVdbe);
- sqlcipher_sqlite3DbFree(db, pVdbe);
+ sqlcipher_sqlite3VdbeDelete(pVdbe);
db->pnBytesFreed = 0;
sqlcipher_sqlite3_mutex_leave(db->mutex);
}else{
@@ -89793,6 +88311,7 @@ SQLITE_API int sqlcipher_sqlite3_preupdate_old(sqlcipher_sqlite3 *db, int iIdx,
u32 nRec;
u8 *aRec;
+ assert( p->pCsr->eCurType==CURTYPE_BTREE );
nRec = sqlcipher_sqlite3BtreePayloadSize(p->pCsr->uc.pCursor);
aRec = sqlcipher_sqlite3DbMallocRaw(db, nRec);
if( !aRec ) goto preupdate_old_out;
@@ -89858,6 +88377,17 @@ SQLITE_API int sqlcipher_sqlite3_preupdate_depth(sqlcipher_sqlite3 *db){
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
/*
+** This function is designed to be called from within a pre-update callback
+** only.
+*/
+SQLITE_API int sqlcipher_sqlite3_preupdate_blobwrite(sqlcipher_sqlite3 *db){
+ PreUpdate *p = db->pPreUpdate;
+ return (p ? p->iBlobWrite : -1);
+}
+#endif
+
+#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
+/*
** This function is called from within a pre-update callback to retrieve
** a field of the row currently being updated or inserted.
*/
@@ -90089,11 +88619,9 @@ SQLITE_PRIVATE char *sqlcipher_sqlite3VdbeExpandSql(
#ifndef SQLITE_OMIT_UTF16
Mem utf8; /* Used to convert UTF16 into UTF8 for display */
#endif
- char zBase[100]; /* Initial working space */
db = p->db;
- sqlcipher_sqlite3StrAccumInit(&out, 0, zBase, sizeof(zBase),
- db->aLimit[SQLITE_LIMIT_LENGTH]);
+ sqlcipher_sqlite3StrAccumInit(&out, 0, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]);
if( db->nVdbeExec>1 ){
while( *zRawSql ){
const char *zStart = zRawSql;
@@ -90130,7 +88658,7 @@ SQLITE_PRIVATE char *sqlcipher_sqlite3VdbeExpandSql(
assert( idx>0 );
}
zRawSql += nToken;
- nextIndex = idx + 1;
+ nextIndex = MAX(idx + 1, nextIndex);
assert( idx>0 && idx<=p->nVar );
pVar = &p->aVar[idx-1];
if( pVar->flags & MEM_Null ){
@@ -90443,7 +88971,6 @@ static VdbeCursor *allocateCursor(
Vdbe *p, /* The virtual machine */
int iCur, /* Index of the new VdbeCursor */
int nField, /* Number of fields in the table or index */
- int iDb, /* Database the cursor belongs to, or -1 */
u8 eCurType /* Type of the new cursor */
){
/* Find the memory cell that will be used to store the blob of memory
@@ -90469,31 +88996,43 @@ static VdbeCursor *allocateCursor(
int nByte;
VdbeCursor *pCx = 0;
nByte =
- ROUND8(sizeof(VdbeCursor)) + 2*sizeof(u32)*nField +
+ ROUND8P(sizeof(VdbeCursor)) + 2*sizeof(u32)*nField +
(eCurType==CURTYPE_BTREE?sqlcipher_sqlite3BtreeCursorSize():0);
assert( iCur>=0 && iCur<p->nCursor );
if( p->apCsr[iCur] ){ /*OPTIMIZATION-IF-FALSE*/
- /* Before calling sqlcipher_sqlite3VdbeFreeCursor(), ensure the isEphemeral flag
- ** is clear. Otherwise, if this is an ephemeral cursor created by
- ** OP_OpenDup, the cursor will not be closed and will still be part
- ** of a BtShared.pCursor list. */
- if( p->apCsr[iCur]->pBtx==0 ) p->apCsr[iCur]->isEphemeral = 0;
- sqlcipher_sqlite3VdbeFreeCursor(p, p->apCsr[iCur]);
+ sqlcipher_sqlite3VdbeFreeCursorNN(p, p->apCsr[iCur]);
p->apCsr[iCur] = 0;
}
- if( SQLITE_OK==sqlcipher_sqlite3VdbeMemClearAndResize(pMem, nByte) ){
- p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->z;
- memset(pCx, 0, offsetof(VdbeCursor,pAltCursor));
- pCx->eCurType = eCurType;
- pCx->iDb = iDb;
- pCx->nField = nField;
- pCx->aOffset = &pCx->aType[nField];
- if( eCurType==CURTYPE_BTREE ){
- pCx->uc.pCursor = (BtCursor*)
- &pMem->z[ROUND8(sizeof(VdbeCursor))+2*sizeof(u32)*nField];
- sqlcipher_sqlite3BtreeCursorZero(pCx->uc.pCursor);
+
+ /* There used to be a call to sqlcipher_sqlite3VdbeMemClearAndResize() to make sure
+ ** the pMem used to hold space for the cursor has enough storage available
+ ** in pMem->zMalloc. But for the special case of the aMem[] entries used
+ ** to hold cursors, it is faster to in-line the logic. */
+ assert( pMem->flags==MEM_Undefined );
+ assert( (pMem->flags & MEM_Dyn)==0 );
+ assert( pMem->szMalloc==0 || pMem->z==pMem->zMalloc );
+ if( pMem->szMalloc<nByte ){
+ if( pMem->szMalloc>0 ){
+ sqlcipher_sqlite3DbFreeNN(pMem->db, pMem->zMalloc);
+ }
+ pMem->z = pMem->zMalloc = sqlcipher_sqlite3DbMallocRaw(pMem->db, nByte);
+ if( pMem->zMalloc==0 ){
+ pMem->szMalloc = 0;
+ return 0;
}
+ pMem->szMalloc = nByte;
+ }
+
+ p->apCsr[iCur] = pCx = (VdbeCursor*)pMem->zMalloc;
+ memset(pCx, 0, offsetof(VdbeCursor,pAltCursor));
+ pCx->eCurType = eCurType;
+ pCx->nField = nField;
+ pCx->aOffset = &pCx->aType[nField];
+ if( eCurType==CURTYPE_BTREE ){
+ pCx->uc.pCursor = (BtCursor*)
+ &pMem->z[ROUND8P(sizeof(VdbeCursor))+2*sizeof(u32)*nField];
+ sqlcipher_sqlite3BtreeCursorZero(pCx->uc.pCursor);
}
return pCx;
}
@@ -90640,7 +89179,10 @@ static u16 SQLITE_NOINLINE computeNumericType(Mem *pMem){
sqlcipher_sqlite3_int64 ix;
assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_IntReal))==0 );
assert( (pMem->flags & (MEM_Str|MEM_Blob))!=0 );
- ExpandBlob(pMem);
+ if( ExpandBlob(pMem) ){
+ pMem->u.i = 0;
+ return MEM_Int;
+ }
rc = sqlcipher_sqlite3AtoF(pMem->z, &pMem->u.r, pMem->n, pMem->enc);
if( rc<=0 ){
if( rc==0 && sqlcipher_sqlite3Atoi64(pMem->z, &ix, pMem->n, pMem->enc)<=1 ){
@@ -90778,6 +89320,11 @@ static void registerTrace(int iReg, Mem *p){
printf("\n");
sqlcipher_sqlite3VdbeCheckMemInvariants(p);
}
+/**/ void sqlcipher_sqlite3PrintMem(Mem *pMem){
+ memTracePrint(pMem);
+ printf("\n");
+ fflush(stdout);
+}
#endif
#ifdef SQLITE_DEBUG
@@ -90805,96 +89352,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3VdbeRegisterDump(Vdbe *v){
** hwtime.h contains inline assembler code for implementing
** high-performance timing routines.
*/
-/************** Include hwtime.h in the middle of vdbe.c *********************/
-/************** 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 and x86_64 class CPUs.
-*/
-#ifndef SQLITE_HWTIME_H
-#define SQLITE_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(__STRICT_ANSI__) && \
- (defined(__GNUC__) || defined(_MSC_VER)) && \
- (defined(i386) || defined(__i386__) || defined(_M_IX86))
-
- #if defined(__GNUC__)
-
- __inline__ sqlite_uint64 sqlcipher_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 sqlcipher_sqlite3Hwtime(void){
- __asm {
- rdtsc
- ret ; return value at EDX:EAX
- }
- }
-
- #endif
-
-#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__))
-
- __inline__ sqlite_uint64 sqlcipher_sqlite3Hwtime(void){
- unsigned long val;
- __asm__ __volatile__ ("rdtsc" : "=A" (val));
- return val;
- }
-
-#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__))
-
- __inline__ sqlite_uint64 sqlcipher_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
-
- /*
- ** asm() is needed for hardware timing support. Without asm(),
- ** disable the sqlcipher_sqlite3Hwtime() routine.
- **
- ** sqlcipher_sqlite3Hwtime() is only used for some obscure debugging
- ** and analysis configurations, not in any deliverable, so this
- ** should not be a great loss.
- */
-SQLITE_PRIVATE sqlite_uint64 sqlcipher_sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
-
-#endif
-
-#endif /* !defined(SQLITE_HWTIME_H) */
-
-/************** End of hwtime.h **********************************************/
-/************** Continuing where we left off in vdbe.c ***********************/
+/* #include "hwtime.h" */
#endif
@@ -90941,6 +89399,42 @@ static Mem *out2Prerelease(Vdbe *p, VdbeOp *pOp){
}
}
+/*
+** Compute a bloom filter hash using pOp->p4.i registers from aMem[] beginning
+** with pOp->p3. Return the hash.
+*/
+static u64 filterHash(const Mem *aMem, const Op *pOp){
+ int i, mx;
+ u64 h = 0;
+
+ assert( pOp->p4type==P4_INT32 );
+ for(i=pOp->p3, mx=i+pOp->p4.i; i<mx; i++){
+ const Mem *p = &aMem[i];
+ if( p->flags & (MEM_Int|MEM_IntReal) ){
+ h += p->u.i;
+ }else if( p->flags & MEM_Real ){
+ h += sqlcipher_sqlite3VdbeIntValue(p);
+ }else if( p->flags & (MEM_Str|MEM_Blob) ){
+ h += p->n;
+ if( p->flags & MEM_Zero ) h += p->u.nZero;
+ }
+ }
+ return h;
+}
+
+/*
+** Return the symbolic name for the data type of a pMem
+*/
+static const char *vdbeMemTypeName(Mem *pMem){
+ static const char *azTypes[] = {
+ /* SQLITE_INTEGER */ "INT",
+ /* SQLITE_FLOAT */ "REAL",
+ /* SQLITE_TEXT */ "TEXT",
+ /* SQLITE_BLOB */ "BLOB",
+ /* SQLITE_NULL */ "NULL"
+ };
+ return azTypes[sqlcipher_sqlite3_value_type(pMem)-1];
+}
/*
** Execute as much of a VDBE program as we can.
@@ -90976,7 +89470,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VdbeExec(
#endif
/*** INSERT STACK UNION HERE ***/
- assert( p->magic==VDBE_MAGIC_RUN ); /* sqlcipher_sqlite3_step() verifies this */
+ assert( p->eVdbeState==VDBE_RUN_STATE ); /* sqlcipher_sqlite3_step() verifies this */
sqlcipher_sqlite3VdbeEnter(p);
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
if( db->xProgress ){
@@ -91219,24 +89713,39 @@ case OP_Gosub: { /* jump */
pIn1->flags = MEM_Int;
pIn1->u.i = (int)(pOp-aOp);
REGISTER_TRACE(pOp->p1, pIn1);
-
- /* Most jump operations do a goto to this spot in order to update
- ** the pOp pointer. */
-jump_to_p2:
- pOp = &aOp[pOp->p2 - 1];
- break;
+ goto jump_to_p2_and_check_for_interrupt;
}
-/* Opcode: Return P1 * * * *
+/* Opcode: Return P1 P2 P3 * *
**
-** Jump to the next instruction after the address in register P1. After
-** the jump, register P1 becomes undefined.
+** Jump to the address stored in register P1. If P1 is a return address
+** register, then this accomplishes a return from a subroutine.
+**
+** If P3 is 1, then the jump is only taken if register P1 holds an integer
+** values, otherwise execution falls through to the next opcode, and the
+** OP_Return becomes a no-op. If P3 is 0, then register P1 must hold an
+** integer or else an assert() is raised. P3 should be set to 1 when
+** this opcode is used in combination with OP_BeginSubrtn, and set to 0
+** otherwise.
+**
+** The value in register P1 is unchanged by this opcode.
+**
+** P2 is not used by the byte-code engine. However, if P2 is positive
+** and also less than the current address, then the "EXPLAIN" output
+** formatter in the CLI will indent all opcodes from the P2 opcode up
+** to be not including the current Return. P2 should be the first opcode
+** in the subroutine from which this opcode is returning. Thus the P2
+** value is a byte-code indentation hint. See tag-20220407a in
+** wherecode.c and shell.c.
*/
case OP_Return: { /* in1 */
pIn1 = &aMem[pOp->p1];
- assert( pIn1->flags==MEM_Int );
- pOp = &aOp[pIn1->u.i];
- pIn1->flags = MEM_Undefined;
+ if( pIn1->flags & MEM_Int ){
+ if( pOp->p3 ){ VdbeBranchTaken(1, 2); }
+ pOp = &aOp[pIn1->u.i];
+ }else if( ALWAYS(pOp->p3) ){
+ VdbeBranchTaken(0, 2);
+ }
break;
}
@@ -91259,7 +89768,14 @@ case OP_InitCoroutine: { /* jump */
assert( !VdbeMemDynamic(pOut) );
pOut->u.i = pOp->p3 - 1;
pOut->flags = MEM_Int;
- if( pOp->p2 ) goto jump_to_p2;
+ if( pOp->p2==0 ) break;
+
+ /* Most jump operations do a goto to this spot in order to update
+ ** the pOp pointer. */
+jump_to_p2:
+ assert( pOp->p2>0 ); /* There are never any jumps to instruction 0 */
+ assert( pOp->p2<p->nOp ); /* Jumps must be in range */
+ pOp = &aOp[pOp->p2 - 1];
break;
}
@@ -91361,11 +89877,10 @@ case OP_Halt: {
VdbeFrame *pFrame;
int pcx;
- pcx = (int)(pOp - aOp);
#ifdef SQLITE_DEBUG
if( pOp->p2==OE_Abort ){ sqlcipher_sqlite3VdbeAssertAbortable(p); }
#endif
- if( pOp->p1==SQLITE_OK && p->pFrame ){
+ if( p->pFrame && pOp->p1==SQLITE_OK ){
/* Halt the sub-program. Return control to the parent frame. */
pFrame = p->pFrame;
p->pFrame = pFrame->pParent;
@@ -91387,7 +89902,6 @@ case OP_Halt: {
}
p->rc = pOp->p1;
p->errorAction = (u8)pOp->p2;
- p->pc = pcx;
assert( pOp->p5<=4 );
if( p->rc ){
if( pOp->p5 ){
@@ -91404,6 +89918,7 @@ case OP_Halt: {
}else{
sqlcipher_sqlite3VdbeError(p, "%s", pOp->p4.z);
}
+ pcx = (int)(pOp - aOp);
sqlcipher_sqlite3_log(pOp->p1, "abort at %d in [%s]: %s", pcx, p->zSql, p->zErrMsg);
}
rc = sqlcipher_sqlite3VdbeHalt(p);
@@ -91529,6 +90044,28 @@ case OP_String: { /* out2 */
break;
}
+/* Opcode: BeginSubrtn * P2 * * *
+** Synopsis: r[P2]=NULL
+**
+** Mark the beginning of a subroutine that can be entered in-line
+** or that can be called using OP_Gosub. The subroutine should
+** be terminated by an OP_Return instruction that has a P1 operand that
+** is the same as the P2 operand to this opcode and that has P3 set to 1.
+** If the subroutine is entered in-line, then the OP_Return will simply
+** fall through. But if the subroutine is entered using OP_Gosub, then
+** the OP_Return will jump back to the first instruction after the OP_Gosub.
+**
+** This routine works by loading a NULL into the P2 register. When the
+** return address register contains a NULL, the OP_Return instruction is
+** a no-op that simply falls through to the next instruction (assuming that
+** the OP_Return opcode has a P3 value of 1). Thus if the subroutine is
+** entered in-line, then the OP_Return will cause in-line execution to
+** continue. But if the subroutine is entered via OP_Gosub, then the
+** OP_Return will cause a return to the address following the OP_Gosub.
+**
+** This opcode is identical to OP_Null. It has a different name
+** only to make the byte code easier to read and verify.
+*/
/* Opcode: Null P1 P2 P3 * *
** Synopsis: r[P2..P3]=NULL
**
@@ -91541,6 +90078,7 @@ case OP_String: { /* out2 */
** NULL values will not compare equal even if SQLITE_NULLEQ is set on
** OP_Ne or OP_Eq.
*/
+case OP_BeginSubrtn:
case OP_Null: { /* out2 */
int cnt;
u16 nullFlag;
@@ -91582,12 +90120,18 @@ case OP_SoftNull: {
** Synopsis: r[P2]=P4 (len=P1)
**
** P4 points to a blob of data P1 bytes long. Store this
-** blob in register P2.
+** blob in register P2. If P4 is a NULL pointer, then construct
+** a zero-filled blob that is P1 bytes long in P2.
*/
case OP_Blob: { /* out2 */
assert( pOp->p1 <= SQLITE_MAX_LENGTH );
pOut = out2Prerelease(p, pOp);
- sqlcipher_sqlite3VdbeMemSetStr(pOut, pOp->p4.z, pOp->p1, 0, 0);
+ if( pOp->p4.z==0 ){
+ sqlcipher_sqlite3VdbeMemSetZeroBlob(pOut, pOp->p1);
+ if( sqlcipher_sqlite3VdbeMemExpandBlob(pOut) ) goto no_mem;
+ }else{
+ sqlcipher_sqlite3VdbeMemSetStr(pOut, pOp->p4.z, pOp->p1, 0, 0);
+ }
pOut->enc = encoding;
UPDATE_MAX_BLOBSIZE(pOut);
break;
@@ -91665,11 +90209,16 @@ case OP_Move: {
break;
}
-/* Opcode: Copy P1 P2 P3 * *
+/* Opcode: Copy P1 P2 P3 * P5
** Synopsis: r[P2@P3+1]=r[P1@P3+1]
**
** Make a copy of registers P1..P1+P3 into registers P2..P2+P3.
**
+** If the 0x0002 bit of P5 is set then also clear the MEM_Subtype flag in the
+** destination. The 0x0001 bit of P5 indicates that this Copy opcode cannot
+** be merged. The 0x0001 bit is used by the query planner and does not
+** come into play during query execution.
+**
** This instruction makes a deep copy of the value. A duplicate
** is made of any string or blob constant. See also OP_SCopy.
*/
@@ -91684,6 +90233,9 @@ case OP_Copy: {
memAboutToChange(p, pOut);
sqlcipher_sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem);
Deephemeralize(pOut);
+ if( (pOut->flags & MEM_Subtype)!=0 && (pOp->p5 & 0x0002)!=0 ){
+ pOut->flags &= ~MEM_Subtype;
+ }
#ifdef SQLITE_DEBUG
pOut->pScopyFrom = 0;
#endif
@@ -91736,6 +90288,24 @@ case OP_IntCopy: { /* out2 */
break;
}
+/* Opcode: FkCheck * * * * *
+**
+** Halt with an SQLITE_CONSTRAINT error if there are any unresolved
+** foreign key constraint violations. If there are no foreign key
+** constraint violations, this is a no-op.
+**
+** FK constraint violations are also checked when the prepared statement
+** exits. This opcode is used to raise foreign key constraint errors prior
+** to returning results such as a row change count or the result of a
+** RETURNING clause.
+*/
+case OP_FkCheck: {
+ if( (rc = sqlcipher_sqlite3VdbeCheckFk(p,0))!=SQLITE_OK ){
+ goto abort_due_to_error;
+ }
+ break;
+}
+
/* Opcode: ResultRow P1 P2 * * *
** Synopsis: output=r[P1@P2]
**
@@ -91746,73 +90316,32 @@ case OP_IntCopy: { /* out2 */
** the result row.
*/
case OP_ResultRow: {
- Mem *pMem;
- int i;
assert( p->nResColumn==pOp->p2 );
- assert( pOp->p1>0 );
+ assert( pOp->p1>0 || CORRUPT_DB );
assert( pOp->p1+pOp->p2<=(p->nMem+1 - p->nCursor)+1 );
- /* If this statement has violated immediate foreign key constraints, do
- ** not return the number of rows modified. And do not RELEASE the statement
- ** transaction. It needs to be rolled back. */
- if( SQLITE_OK!=(rc = sqlcipher_sqlite3VdbeCheckFk(p, 0)) ){
- assert( db->flags&SQLITE_CountRows );
- assert( p->usesStmtJournal );
- goto abort_due_to_error;
- }
-
- /* If the SQLITE_CountRows flag is set in sqlcipher_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.
- **
- ** In case this is such a statement, close any statement transaction
- ** opened by this VM before returning control to the user. This is to
- ** ensure that statement-transactions are always nested, not overlapping.
- ** If the open statement-transaction is not closed here, then the user
- ** may step another VM that opens its own statement transaction. This
- ** may lead to overlapping statement transactions.
- **
- ** The statement transaction is never a top-level transaction. Hence
- ** the RELEASE call below can never fail.
- */
- assert( p->iStatement==0 || db->flags&SQLITE_CountRows );
- rc = sqlcipher_sqlite3VdbeCloseStatement(p, SAVEPOINT_RELEASE);
- assert( rc==SQLITE_OK );
-
- /* Invalidate all ephemeral cursor row caches */
p->cacheCtr = (p->cacheCtr + 2)|1;
-
- /* Make sure the results of the current row are \000 terminated
- ** and have an assigned type. The results are de-ephemeralized as
- ** a side effect.
- */
- 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 );
- sqlcipher_sqlite3VdbeMemNulTerminate(&pMem[i]);
- REGISTER_TRACE(pOp->p1+i, &pMem[i]);
+ p->pResultSet = &aMem[pOp->p1];
#ifdef SQLITE_DEBUG
- /* The registers in the result will not be used again when the
- ** prepared statement restarts. This is because sqlcipher_sqlite3_column()
- ** APIs might have caused type conversions of made other changes to
- ** the register values. Therefore, we can go ahead and break any
- ** OP_SCopy dependencies. */
- pMem[i].pScopyFrom = 0;
-#endif
+ {
+ Mem *pMem = p->pResultSet;
+ int i;
+ for(i=0; i<pOp->p2; i++){
+ assert( memIsValid(&pMem[i]) );
+ REGISTER_TRACE(pOp->p1+i, &pMem[i]);
+ /* The registers in the result will not be used again when the
+ ** prepared statement restarts. This is because sqlcipher_sqlite3_column()
+ ** APIs might have caused type conversions of made other changes to
+ ** the register values. Therefore, we can go ahead and break any
+ ** OP_SCopy dependencies. */
+ pMem[i].pScopyFrom = 0;
+ }
}
+#endif
if( db->mallocFailed ) goto no_mem;
-
if( db->mTrace & SQLITE_TRACE_ROW ){
db->trace.xV2(SQLITE_TRACE_ROW, db->pTraceArg, p, 0);
}
-
-
- /* Return SQLITE_ROW
- */
p->pc = (int)(pOp - aOp) + 1;
rc = SQLITE_ROW;
goto vdbe_return;
@@ -91867,7 +90396,7 @@ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */
if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
- if( sqlcipher_sqlite3VdbeMemGrow(pOut, (int)nByte+3, pOut==pIn2) ){
+ if( sqlcipher_sqlite3VdbeMemGrow(pOut, (int)nByte+2, pOut==pIn2) ){
goto no_mem;
}
MemSetTypeFlag(pOut, MEM_Str);
@@ -91879,9 +90408,9 @@ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */
memcpy(&pOut->z[pIn2->n], pIn1->z, pIn1->n);
assert( (pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn) );
pIn1->flags = flags1;
+ if( encoding>SQLITE_UTF8 ) nByte &= ~1;
pOut->z[nByte]=0;
pOut->z[nByte+1] = 0;
- pOut->z[nByte+2] = 0;
pOut->flags |= MEM_Term;
pOut->n = (int)nByte;
pOut->enc = encoding;
@@ -92219,8 +90748,7 @@ case OP_Cast: { /* in1 */
** Synopsis: IF r[P3]==r[P1]
**
** Compare the values in register P1 and P3. If reg(P3)==reg(P1) then
-** jump to address P2. Or if the SQLITE_STOREP2 flag is set in P5, then
-** store the result of comparison in register P2.
+** jump to address P2.
**
** The SQLITE_AFF_MASK portion of P5 must be an affinity character -
** SQLITE_AFF_TEXT, SQLITE_AFF_INTEGER, and so forth. An attempt is made
@@ -92246,9 +90774,8 @@ case OP_Cast: { /* in1 */
** If neither operand is NULL the result is the same as it would be if
** the SQLITE_NULLEQ flag were omitted from P5.
**
-** If both SQLITE_STOREP2 and SQLITE_KEEPNULL flags are set then the
-** content of r[P2] is only changed if the new value is NULL or 0 (false).
-** In other words, a prior r[P2] value will not be overwritten by 1 (true).
+** This opcode saves the result of comparison for use by the new
+** OP_Jump opcode.
*/
/* Opcode: Ne P1 P2 P3 P4 P5
** Synopsis: IF r[P3]!=r[P1]
@@ -92256,17 +90783,12 @@ case OP_Cast: { /* in1 */
** This works just like the Eq opcode except that the jump is taken if
** the operands in registers P1 and P3 are not equal. See the Eq opcode for
** additional information.
-**
-** If both SQLITE_STOREP2 and SQLITE_KEEPNULL flags are set then the
-** content of r[P2] is only changed if the new value is NULL or 1 (true).
-** In other words, a prior r[P2] value will not be overwritten by 0 (false).
*/
/* Opcode: Lt P1 P2 P3 P4 P5
** Synopsis: IF r[P3]<r[P1]
**
** Compare the values in register P1 and P3. If reg(P3)<reg(P1) then
-** jump to address P2. Or if the SQLITE_STOREP2 flag is set in P5 store
-** the result of comparison (0 or 1 or NULL) into register P2.
+** jump to address P2.
**
** If the SQLITE_JUMPIFNULL bit of P5 is set and either reg(P1) or
** reg(P3) is NULL then the take the jump. If the SQLITE_JUMPIFNULL
@@ -92289,6 +90811,9 @@ case OP_Cast: { /* in1 */
** numeric, then a numeric comparison is used. If the two values
** are of different types, then numbers are considered less than
** strings and strings are considered less than blobs.
+**
+** This opcode saves the result of comparison for use by the new
+** OP_Jump opcode.
*/
/* Opcode: Le P1 P2 P3 P4 P5
** Synopsis: IF r[P3]<=r[P1]
@@ -92326,6 +90851,31 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
pIn3 = &aMem[pOp->p3];
flags1 = pIn1->flags;
flags3 = pIn3->flags;
+ if( (flags1 & flags3 & MEM_Int)!=0 ){
+ assert( (pOp->p5 & SQLITE_AFF_MASK)!=SQLITE_AFF_TEXT || CORRUPT_DB );
+ /* Common case of comparison of two integers */
+ if( pIn3->u.i > pIn1->u.i ){
+ if( sqlcipher_sqlite3aGTb[pOp->opcode] ){
+ VdbeBranchTaken(1, (pOp->p5 & SQLITE_NULLEQ)?2:3);
+ goto jump_to_p2;
+ }
+ iCompare = +1;
+ }else if( pIn3->u.i < pIn1->u.i ){
+ if( sqlcipher_sqlite3aLTb[pOp->opcode] ){
+ VdbeBranchTaken(1, (pOp->p5 & SQLITE_NULLEQ)?2:3);
+ goto jump_to_p2;
+ }
+ iCompare = -1;
+ }else{
+ if( sqlcipher_sqlite3aEQb[pOp->opcode] ){
+ VdbeBranchTaken(1, (pOp->p5 & SQLITE_NULLEQ)?2:3);
+ goto jump_to_p2;
+ }
+ iCompare = 0;
+ }
+ VdbeBranchTaken(0, (pOp->p5 & SQLITE_NULLEQ)?2:3);
+ break;
+ }
if( (flags1 | flags3)&MEM_Null ){
/* One or both operands are NULL */
if( pOp->p5 & SQLITE_NULLEQ ){
@@ -92348,22 +90898,16 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
** then the result is always NULL.
** The jump is taken if the SQLITE_JUMPIFNULL bit is set.
*/
- if( pOp->p5 & SQLITE_STOREP2 ){
- pOut = &aMem[pOp->p2];
- iCompare = 1; /* Operands are not equal */
- memAboutToChange(p, pOut);
- MemSetTypeFlag(pOut, MEM_Null);
- REGISTER_TRACE(pOp->p2, pOut);
- }else{
- VdbeBranchTaken(2,3);
- if( pOp->p5 & SQLITE_JUMPIFNULL ){
- goto jump_to_p2;
- }
+ VdbeBranchTaken(2,3);
+ if( pOp->p5 & SQLITE_JUMPIFNULL ){
+ goto jump_to_p2;
}
+ iCompare = 1; /* Operands are not equal */
break;
}
}else{
- /* Neither operand is NULL. Do a comparison. */
+ /* Neither operand is NULL and we couldn't do the special high-speed
+ ** integer comparison case. So do a general-case comparison. */
affinity = pOp->p5 & SQLITE_AFF_MASK;
if( affinity>=SQLITE_AFF_NUMERIC ){
if( (flags1 | flags3)&MEM_Str ){
@@ -92376,14 +90920,6 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
applyNumericAffinity(pIn3,0);
}
}
- /* Handle the common case of integer comparison here, as an
- ** optimization, to avoid a call to sqlcipher_sqlite3MemCompare() */
- if( (pIn1->flags & pIn3->flags & MEM_Int)!=0 ){
- if( pIn3->u.i > pIn1->u.i ){ res = +1; goto compare_op; }
- if( pIn3->u.i < pIn1->u.i ){ res = -1; goto compare_op; }
- res = 0;
- goto compare_op;
- }
}else if( affinity==SQLITE_AFF_TEXT ){
if( (flags1 & MEM_Str)==0 && (flags1&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){
testcase( pIn1->flags & MEM_Int );
@@ -92392,7 +90928,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
sqlcipher_sqlite3VdbeMemStringify(pIn1, encoding, 1);
testcase( (flags1&MEM_Dyn) != (pIn1->flags&MEM_Dyn) );
flags1 = (pIn1->flags & ~MEM_TypeMask) | (flags1 & MEM_TypeMask);
- if( NEVER(pIn1==pIn3) ) flags3 = flags1 | MEM_Str;
+ if( pIn1==pIn3 ) flags3 = flags1 | MEM_Str;
}
if( (flags3 & MEM_Str)==0 && (flags3&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){
testcase( pIn3->flags & MEM_Int );
@@ -92406,7 +90942,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 );
res = sqlcipher_sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl);
}
-compare_op:
+
/* At this point, res is negative, zero, or positive if reg[P1] is
** less than, equal to, or greater than reg[P3], respectively. Compute
** the answer to this operator in res2, depending on what the comparison
@@ -92415,16 +90951,14 @@ compare_op:
** order: NE, EQ, GT, LE, LT, GE */
assert( OP_Eq==OP_Ne+1 ); assert( OP_Gt==OP_Ne+2 ); assert( OP_Le==OP_Ne+3 );
assert( OP_Lt==OP_Ne+4 ); assert( OP_Ge==OP_Ne+5 );
- if( res<0 ){ /* ne, eq, gt, le, lt, ge */
- static const unsigned char aLTb[] = { 1, 0, 0, 1, 1, 0 };
- res2 = aLTb[pOp->opcode - OP_Ne];
+ if( res<0 ){
+ res2 = sqlcipher_sqlite3aLTb[pOp->opcode];
}else if( res==0 ){
- static const unsigned char aEQb[] = { 0, 1, 0, 1, 0, 1 };
- res2 = aEQb[pOp->opcode - OP_Ne];
+ res2 = sqlcipher_sqlite3aEQb[pOp->opcode];
}else{
- static const unsigned char aGTb[] = { 1, 0, 1, 0, 0, 1 };
- res2 = aGTb[pOp->opcode - OP_Ne];
+ res2 = sqlcipher_sqlite3aGTb[pOp->opcode];
}
+ iCompare = res;
/* Undo any changes made by applyAffinity() to the input registers. */
assert( (pIn3->flags & MEM_Dyn) == (flags3 & MEM_Dyn) );
@@ -92432,67 +90966,39 @@ compare_op:
assert( (pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn) );
pIn1->flags = flags1;
- if( pOp->p5 & SQLITE_STOREP2 ){
- pOut = &aMem[pOp->p2];
- iCompare = res;
- if( (pOp->p5 & SQLITE_KEEPNULL)!=0 ){
- /* The KEEPNULL flag prevents OP_Eq from overwriting a NULL with 1
- ** and prevents OP_Ne from overwriting NULL with 0. This flag
- ** is only used in contexts where either:
- ** (1) op==OP_Eq && (r[P2]==NULL || r[P2]==0)
- ** (2) op==OP_Ne && (r[P2]==NULL || r[P2]==1)
- ** Therefore it is not necessary to check the content of r[P2] for
- ** NULL. */
- assert( pOp->opcode==OP_Ne || pOp->opcode==OP_Eq );
- assert( res2==0 || res2==1 );
- testcase( res2==0 && pOp->opcode==OP_Eq );
- testcase( res2==1 && pOp->opcode==OP_Eq );
- testcase( res2==0 && pOp->opcode==OP_Ne );
- testcase( res2==1 && pOp->opcode==OP_Ne );
- if( (pOp->opcode==OP_Eq)==res2 ) break;
- }
- memAboutToChange(p, pOut);
- MemSetTypeFlag(pOut, MEM_Int);
- pOut->u.i = res2;
- REGISTER_TRACE(pOp->p2, pOut);
- }else{
- VdbeBranchTaken(res2!=0, (pOp->p5 & SQLITE_NULLEQ)?2:3);
- if( res2 ){
- goto jump_to_p2;
- }
+ VdbeBranchTaken(res2!=0, (pOp->p5 & SQLITE_NULLEQ)?2:3);
+ if( res2 ){
+ goto jump_to_p2;
}
break;
}
-/* Opcode: ElseNotEq * P2 * * *
+/* Opcode: ElseEq * P2 * * *
**
** This opcode must follow an OP_Lt or OP_Gt comparison operator. There
** can be zero or more OP_ReleaseReg opcodes intervening, but no other
** opcodes are allowed to occur between this instruction and the previous
-** OP_Lt or OP_Gt. Furthermore, the prior OP_Lt or OP_Gt must have the
-** SQLITE_STOREP2 bit set in the P5 field.
+** OP_Lt or OP_Gt.
**
** If result of an OP_Eq comparison on the same two operands as the
-** prior OP_Lt or OP_Gt would have been NULL or false (0), then then
-** jump to P2. If the result of an OP_Eq comparison on the two previous
-** operands would have been true (1), then fall through.
+** prior OP_Lt or OP_Gt would have been true, then jump to P2.
+** If the result of an OP_Eq comparison on the two previous
+** operands would have been false or NULL, then fall through.
*/
-case OP_ElseNotEq: { /* same as TK_ESCAPE, jump */
+case OP_ElseEq: { /* same as TK_ESCAPE, jump */
#ifdef SQLITE_DEBUG
/* Verify the preconditions of this opcode - that it follows an OP_Lt or
- ** OP_Gt with the SQLITE_STOREP2 flag set, with zero or more intervening
- ** OP_ReleaseReg opcodes */
+ ** OP_Gt with zero or more intervening OP_ReleaseReg opcodes */
int iAddr;
for(iAddr = (int)(pOp - aOp) - 1; ALWAYS(iAddr>=0); iAddr--){
if( aOp[iAddr].opcode==OP_ReleaseReg ) continue;
assert( aOp[iAddr].opcode==OP_Lt || aOp[iAddr].opcode==OP_Gt );
- assert( aOp[iAddr].p5 & SQLITE_STOREP2 );
break;
}
#endif /* SQLITE_DEBUG */
- VdbeBranchTaken(iCompare!=0, 2);
- if( iCompare!=0 ) goto jump_to_p2;
+ VdbeBranchTaken(iCompare==0, 2);
+ if( iCompare==0 ) goto jump_to_p2;
break;
}
@@ -92502,9 +91008,8 @@ case OP_ElseNotEq: { /* same as TK_ESCAPE, jump */
** Set the permutation used by the OP_Compare operator in the next
** instruction. The permutation is stored in the P4 operand.
**
-** The permutation is only valid until the next OP_Compare that has
-** the OPFLAG_PERMUTE bit set in P5. Typically the OP_Permutation should
-** occur immediately prior to the OP_Compare.
+** The permutation is only valid for the next opcode which must be
+** an OP_Compare that has the OPFLAG_PERMUTE bit set in P5.
**
** The first integer in the P4 integer array is the length of the array
** and does not become part of the permutation.
@@ -92536,6 +91041,8 @@ case OP_Permutation: {
** The comparison is a sort comparison, so NULLs compare equal,
** NULLs are less than numbers, numbers are less than strings,
** and strings are less than blobs.
+**
+** This opcode must be immediately followed by an OP_Jump opcode.
*/
case OP_Compare: {
int n;
@@ -92594,6 +91101,7 @@ case OP_Compare: {
break;
}
}
+ assert( pOp[1].opcode==OP_Jump );
break;
}
@@ -92602,8 +91110,11 @@ case OP_Compare: {
** Jump to the instruction at address P1, P2, or P3 depending on whether
** in the most recent OP_Compare instruction the P1 vector was less than
** equal to, or greater than the P2 vector, respectively.
+**
+** This opcode must immediately follow an OP_Compare opcode.
*/
case OP_Jump: { /* jump */
+ assert( pOp>aOp && pOp[-1].opcode==OP_Compare );
if( iCompare<0 ){
VdbeBranchTaken(0,4); pOp = &aOp[pOp->p1 - 1];
}else if( iCompare==0 ){
@@ -92803,6 +91314,40 @@ case OP_IsNull: { /* same as TK_ISNULL, jump, in1 */
break;
}
+/* Opcode: IsNullOrType P1 P2 P3 * *
+** Synopsis: if typeof(r[P1]) IN (P3,5) goto P2
+**
+** Jump to P2 if the value in register P1 is NULL or has a datatype P3.
+** P3 is an integer which should be one of SQLITE_INTEGER, SQLITE_FLOAT,
+** SQLITE_BLOB, SQLITE_NULL, or SQLITE_TEXT.
+*/
+case OP_IsNullOrType: { /* jump, in1 */
+ int doTheJump;
+ pIn1 = &aMem[pOp->p1];
+ doTheJump = (pIn1->flags & MEM_Null)!=0 || sqlcipher_sqlite3_value_type(pIn1)==pOp->p3;
+ VdbeBranchTaken( doTheJump, 2);
+ if( doTheJump ) goto jump_to_p2;
+ break;
+}
+
+/* Opcode: ZeroOrNull P1 P2 P3 * *
+** Synopsis: r[P2] = 0 OR NULL
+**
+** If all both registers P1 and P3 are NOT NULL, then store a zero in
+** register P2. If either registers P1 or P3 are NULL then put
+** a NULL in register P2.
+*/
+case OP_ZeroOrNull: { /* in1, in2, out2, in3 */
+ if( (aMem[pOp->p1].flags & MEM_Null)!=0
+ || (aMem[pOp->p3].flags & MEM_Null)!=0
+ ){
+ sqlcipher_sqlite3VdbeMemSetNull(aMem + pOp->p2);
+ }else{
+ sqlcipher_sqlite3VdbeMemSetInt64(aMem + pOp->p2, 0);
+ }
+ break;
+}
+
/* Opcode: NotNull P1 P2 * * *
** Synopsis: if r[P1]!=NULL goto P2
**
@@ -92856,17 +91401,25 @@ case OP_Offset: { /* out3 */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
pOut = &p->aMem[pOp->p3];
- if( NEVER(pC==0) || pC->eCurType!=CURTYPE_BTREE ){
+ if( pC==0 || pC->eCurType!=CURTYPE_BTREE ){
sqlcipher_sqlite3VdbeMemSetNull(pOut);
}else{
- sqlcipher_sqlite3VdbeMemSetInt64(pOut, sqlcipher_sqlite3BtreeOffset(pC->uc.pCursor));
+ if( pC->deferredMoveto ){
+ rc = sqlcipher_sqlite3VdbeFinishMoveto(pC);
+ if( rc ) goto abort_due_to_error;
+ }
+ if( sqlcipher_sqlite3BtreeEof(pC->uc.pCursor) ){
+ sqlcipher_sqlite3VdbeMemSetNull(pOut);
+ }else{
+ sqlcipher_sqlite3VdbeMemSetInt64(pOut, sqlcipher_sqlite3BtreeOffset(pC->uc.pCursor));
+ }
}
break;
}
#endif /* SQLITE_ENABLE_OFFSET_SQL_FUNC */
/* Opcode: Column P1 P2 P3 P4 P5
-** Synopsis: r[P3]=PX
+** Synopsis: r[P3]=PX cursor P1 column P2
**
** Interpret the data that cursor P1 points to as a structure built using
** the MakeRecord instruction. (See the MakeRecord opcode for additional
@@ -92888,7 +91441,7 @@ case OP_Offset: { /* out3 */
case OP_Column: {
u32 p2; /* column number to retrieve */
VdbeCursor *pC; /* The VDBE cursor */
- BtCursor *pCrsr; /* The BTree cursor */
+ BtCursor *pCrsr; /* The B-Tree cursor corresponding to pC */
u32 *aOffset; /* aOffset[i] is offset to start of data for i-th column */
int len; /* The length of the serialized data for the column */
int i; /* Loop counter */
@@ -92902,43 +91455,53 @@ case OP_Column: {
Mem *pReg; /* PseudoTable input register */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
pC = p->apCsr[pOp->p1];
- assert( pC!=0 );
p2 = (u32)pOp->p2;
- /* If the cursor cache is stale (meaning it is not currently point at
- ** the correct row) then bring it up-to-date by doing the necessary
- ** B-Tree seek. */
- rc = sqlcipher_sqlite3VdbeCursorMoveto(&pC, &p2);
- if( rc ) goto abort_due_to_error;
-
- assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
- pDest = &aMem[pOp->p3];
- memAboutToChange(p, pDest);
+op_column_restart:
assert( pC!=0 );
- assert( p2<(u32)pC->nField );
+ assert( p2<(u32)pC->nField
+ || (pC->eCurType==CURTYPE_PSEUDO && pC->seekResult==0) );
aOffset = pC->aOffset;
+ assert( aOffset==pC->aType+pC->nField );
assert( pC->eCurType!=CURTYPE_VTAB );
assert( pC->eCurType!=CURTYPE_PSEUDO || pC->nullRow );
assert( pC->eCurType!=CURTYPE_SORTER );
if( pC->cacheStatus!=p->cacheCtr ){ /*OPTIMIZATION-IF-FALSE*/
if( pC->nullRow ){
- if( pC->eCurType==CURTYPE_PSEUDO ){
+ if( pC->eCurType==CURTYPE_PSEUDO && pC->seekResult>0 ){
/* For the special case of as pseudo-cursor, the seekResult field
** identifies the register that holds the record */
- assert( pC->seekResult>0 );
pReg = &aMem[pC->seekResult];
assert( pReg->flags & MEM_Blob );
assert( memIsValid(pReg) );
pC->payloadSize = pC->szRow = pReg->n;
pC->aRow = (u8*)pReg->z;
}else{
+ pDest = &aMem[pOp->p3];
+ memAboutToChange(p, pDest);
sqlcipher_sqlite3VdbeMemSetNull(pDest);
goto op_column_out;
}
}else{
pCrsr = pC->uc.pCursor;
+ if( pC->deferredMoveto ){
+ u32 iMap;
+ assert( !pC->isEphemeral );
+ if( pC->ub.aAltMap && (iMap = pC->ub.aAltMap[1+p2])>0 ){
+ pC = pC->pAltCursor;
+ p2 = iMap - 1;
+ goto op_column_restart;
+ }
+ rc = sqlcipher_sqlite3VdbeFinishMoveto(pC);
+ if( rc ) goto abort_due_to_error;
+ }else if( sqlcipher_sqlite3BtreeCursorHasMoved(pCrsr) ){
+ rc = sqlcipher_sqlite3VdbeHandleMovedCursor(pC);
+ if( rc ) goto abort_due_to_error;
+ goto op_column_restart;
+ }
assert( pC->eCurType==CURTYPE_BTREE );
assert( pCrsr );
assert( sqlcipher_sqlite3BtreeCursorIsValid(pCrsr) );
@@ -92946,15 +91509,15 @@ case OP_Column: {
pC->aRow = sqlcipher_sqlite3BtreePayloadFetch(pCrsr, &pC->szRow);
assert( pC->szRow<=pC->payloadSize );
assert( pC->szRow<=65536 ); /* Maximum page size is 64KiB */
- if( pC->payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
- goto too_big;
- }
}
pC->cacheStatus = p->cacheCtr;
- pC->iHdrOffset = getVarint32(pC->aRow, aOffset[0]);
+ if( (aOffset[0] = pC->aRow[0])<0x80 ){
+ pC->iHdrOffset = 1;
+ }else{
+ pC->iHdrOffset = sqlcipher_sqlite3GetVarint32(pC->aRow, aOffset);
+ }
pC->nHdrParsed = 0;
-
if( pC->szRow<aOffset[0] ){ /*OPTIMIZATION-IF-FALSE*/
/* 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
@@ -92994,6 +91557,10 @@ case OP_Column: {
testcase( aOffset[0]==0 );
goto op_column_read_header;
}
+ }else if( sqlcipher_sqlite3BtreeCursorHasMoved(pC->uc.pCursor) ){
+ rc = sqlcipher_sqlite3VdbeHandleMovedCursor(pC);
+ if( rc ) goto abort_due_to_error;
+ goto op_column_restart;
}
/* Make sure at least the first p2+1 entries of the header have been
@@ -93062,6 +91629,8 @@ case OP_Column: {
** columns. So the result will be either the default value or a NULL.
*/
if( pC->nHdrParsed<=p2 ){
+ pDest = &aMem[pOp->p3];
+ memAboutToChange(p, pDest);
if( pOp->p4type==P4_MEM ){
sqlcipher_sqlite3VdbeMemShallowCopy(pDest, pOp->p4.pMem, MEM_Static);
}else{
@@ -93079,6 +91648,8 @@ case OP_Column: {
*/
assert( p2<pC->nHdrParsed );
assert( rc==SQLITE_OK );
+ pDest = &aMem[pOp->p3];
+ memAboutToChange(p, pDest);
assert( sqlcipher_sqlite3VdbeCheckMemInvariants(pDest) );
if( VdbeMemDynamic(pDest) ){
sqlcipher_sqlite3VdbeMemSetNull(pDest);
@@ -93099,6 +91670,7 @@ case OP_Column: {
pDest->n = len = (t-12)/2;
pDest->enc = encoding;
if( pDest->szMalloc < len+2 ){
+ if( len>db->aLimit[SQLITE_LIMIT_LENGTH] ) goto too_big;
pDest->flags = MEM_Null;
if( sqlcipher_sqlite3VdbeMemGrow(pDest, len+2, 0) ) goto no_mem;
}else{
@@ -93131,6 +91703,7 @@ case OP_Column: {
*/
sqlcipher_sqlite3VdbeSerialGet((u8*)sqlcipher_sqlite3CtypeMap, t, pDest);
}else{
+ if( len>db->aLimit[SQLITE_LIMIT_LENGTH] ) goto too_big;
rc = sqlcipher_sqlite3VdbeMemFromBtree(pC->uc.pCursor, aOffset[p2], len, pDest);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
sqlcipher_sqlite3VdbeSerialGet((const u8*)pDest->z, t, pDest);
@@ -93153,6 +91726,110 @@ op_column_corrupt:
}
}
+/* Opcode: TypeCheck P1 P2 P3 P4 *
+** Synopsis: typecheck(r[P1@P2])
+**
+** Apply affinities to the range of P2 registers beginning with P1.
+** Take the affinities from the Table object in P4. If any value
+** cannot be coerced into the correct type, then raise an error.
+**
+** This opcode is similar to OP_Affinity except that this opcode
+** forces the register type to the Table column type. This is used
+** to implement "strict affinity".
+**
+** GENERATED ALWAYS AS ... STATIC columns are only checked if P3
+** is zero. When P3 is non-zero, no type checking occurs for
+** static generated columns. Virtual columns are computed at query time
+** and so they are never checked.
+**
+** Preconditions:
+**
+** <ul>
+** <li> P2 should be the number of non-virtual columns in the
+** table of P4.
+** <li> Table P4 should be a STRICT table.
+** </ul>
+**
+** If any precondition is false, an assertion fault occurs.
+*/
+case OP_TypeCheck: {
+ Table *pTab;
+ Column *aCol;
+ int i;
+
+ assert( pOp->p4type==P4_TABLE );
+ pTab = pOp->p4.pTab;
+ assert( pTab->tabFlags & TF_Strict );
+ assert( pTab->nNVCol==pOp->p2 );
+ aCol = pTab->aCol;
+ pIn1 = &aMem[pOp->p1];
+ for(i=0; i<pTab->nCol; i++){
+ if( aCol[i].colFlags & COLFLAG_GENERATED ){
+ if( aCol[i].colFlags & COLFLAG_VIRTUAL ) continue;
+ if( pOp->p3 ){ pIn1++; continue; }
+ }
+ assert( pIn1 < &aMem[pOp->p1+pOp->p2] );
+ applyAffinity(pIn1, aCol[i].affinity, encoding);
+ if( (pIn1->flags & MEM_Null)==0 ){
+ switch( aCol[i].eCType ){
+ case COLTYPE_BLOB: {
+ if( (pIn1->flags & MEM_Blob)==0 ) goto vdbe_type_error;
+ break;
+ }
+ case COLTYPE_INTEGER:
+ case COLTYPE_INT: {
+ if( (pIn1->flags & MEM_Int)==0 ) goto vdbe_type_error;
+ break;
+ }
+ case COLTYPE_TEXT: {
+ if( (pIn1->flags & MEM_Str)==0 ) goto vdbe_type_error;
+ break;
+ }
+ case COLTYPE_REAL: {
+ testcase( (pIn1->flags & (MEM_Real|MEM_IntReal))==MEM_Real );
+ testcase( (pIn1->flags & (MEM_Real|MEM_IntReal))==MEM_IntReal );
+ if( pIn1->flags & MEM_Int ){
+ /* When applying REAL affinity, if the result is still an MEM_Int
+ ** that will fit in 6 bytes, then change the type to MEM_IntReal
+ ** so that we keep the high-resolution integer value but know that
+ ** the type really wants to be REAL. */
+ testcase( pIn1->u.i==140737488355328LL );
+ testcase( pIn1->u.i==140737488355327LL );
+ testcase( pIn1->u.i==-140737488355328LL );
+ testcase( pIn1->u.i==-140737488355329LL );
+ if( pIn1->u.i<=140737488355327LL && pIn1->u.i>=-140737488355328LL){
+ pIn1->flags |= MEM_IntReal;
+ pIn1->flags &= ~MEM_Int;
+ }else{
+ pIn1->u.r = (double)pIn1->u.i;
+ pIn1->flags |= MEM_Real;
+ pIn1->flags &= ~MEM_Int;
+ }
+ }else if( (pIn1->flags & (MEM_Real|MEM_IntReal))==0 ){
+ goto vdbe_type_error;
+ }
+ break;
+ }
+ default: {
+ /* COLTYPE_ANY. Accept anything. */
+ break;
+ }
+ }
+ }
+ REGISTER_TRACE((int)(pIn1-aMem), pIn1);
+ pIn1++;
+ }
+ assert( pIn1 == &aMem[pOp->p1+pOp->p2] );
+ break;
+
+vdbe_type_error:
+ sqlcipher_sqlite3VdbeError(p, "cannot store %s value in %s column %s.%s",
+ vdbeMemTypeName(pIn1), sqlcipher_sqlite3StdType[aCol[i].eCType-1],
+ pTab->zName, aCol[i].zCnName);
+ rc = SQLITE_CONSTRAINT_DATATYPE;
+ goto abort_due_to_error;
+}
+
/* Opcode: Affinity P1 P2 * P4 *
** Synopsis: affinity(r[P1@P2])
**
@@ -93239,7 +91916,6 @@ case OP_MakeRecord: {
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 */
u32 len; /* Length of a field */
u8 *zHdr; /* Where to write next byte of the header */
u8 *zPayload; /* Where to write next byte of the payload */
@@ -93268,7 +91944,6 @@ case OP_MakeRecord: {
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 );
@@ -93367,10 +92042,10 @@ case OP_MakeRecord: {
testcase( uu==127 ); testcase( uu==128 );
testcase( uu==32767 ); testcase( uu==32768 );
testcase( uu==8388607 ); testcase( uu==8388608 );
- testcase( uu==2147483647 ); testcase( uu==2147483648 );
+ testcase( uu==2147483647 ); testcase( uu==2147483648LL );
testcase( uu==140737488355327LL ); testcase( uu==140737488355328LL );
if( uu<=127 ){
- if( (i&1)==i && file_format>=4 ){
+ if( (i&1)==i && p->minWriteFileFormat>=4 ){
pRec->uTemp = 8+(u32)uu;
}else{
nData++;
@@ -93475,18 +92150,60 @@ case OP_MakeRecord: {
zPayload = zHdr + nHdr;
/* Write the record */
- zHdr += putVarint32(zHdr, nHdr);
+ if( nHdr<0x80 ){
+ *(zHdr++) = nHdr;
+ }else{
+ zHdr += sqlcipher_sqlite3PutVarint(zHdr,nHdr);
+ }
assert( pData0<=pLast );
pRec = pData0;
- do{
+ while( 1 /*exit-by-break*/ ){
serial_type = pRec->uTemp;
/* EVIDENCE-OF: R-06529-47362 Following the size varint are one or more
- ** additional varints, one per column. */
- zHdr += putVarint32(zHdr, serial_type); /* serial type */
- /* EVIDENCE-OF: R-64536-51728 The values for each column in the record
+ ** additional varints, one per column.
+ ** EVIDENCE-OF: R-64536-51728 The values for each column in the record
** immediately follow the header. */
- zPayload += sqlcipher_sqlite3VdbeSerialPut(zPayload, pRec, serial_type); /* content */
- }while( (++pRec)<=pLast );
+ if( serial_type<=7 ){
+ *(zHdr++) = serial_type;
+ if( serial_type==0 ){
+ /* NULL value. No change in zPayload */
+ }else{
+ u64 v;
+ u32 i;
+ if( serial_type==7 ){
+ assert( sizeof(v)==sizeof(pRec->u.r) );
+ memcpy(&v, &pRec->u.r, sizeof(v));
+ swapMixedEndianFloat(v);
+ }else{
+ v = pRec->u.i;
+ }
+ len = i = sqlcipher_sqlite3SmallTypeSizes[serial_type];
+ assert( i>0 );
+ while( 1 /*exit-by-break*/ ){
+ zPayload[--i] = (u8)(v&0xFF);
+ if( i==0 ) break;
+ v >>= 8;
+ }
+ zPayload += len;
+ }
+ }else if( serial_type<0x80 ){
+ *(zHdr++) = serial_type;
+ if( serial_type>=14 && pRec->n>0 ){
+ assert( pRec->z!=0 );
+ memcpy(zPayload, pRec->z, pRec->n);
+ zPayload += pRec->n;
+ }
+ }else{
+ zHdr += sqlcipher_sqlite3PutVarint(zHdr, serial_type);
+ if( pRec->n ){
+ assert( pRec->z!=0 );
+ memcpy(zPayload, pRec->z, pRec->n);
+ zPayload += pRec->n;
+ }
+ }
+ if( pRec==pLast ) break;
+ pRec++;
+ }
assert( nHdr==(int)(zHdr - (u8*)pOut->z) );
assert( nByte==(int)(zPayload - (u8*)pOut->z) );
@@ -93495,7 +92212,7 @@ case OP_MakeRecord: {
break;
}
-/* Opcode: Count P1 P2 p3 * *
+/* Opcode: Count P1 P2 P3 * *
** Synopsis: r[P2]=count()
**
** Store the number of entries (an integer value) in the table or index
@@ -93705,7 +92422,10 @@ case OP_Savepoint: {
}
}
if( rc ) goto abort_due_to_error;
-
+ if( p->eVdbeState==VDBE_HALT_STATE ){
+ rc = SQLITE_DONE;
+ goto vdbe_return;
+ }
break;
}
@@ -93809,6 +92529,7 @@ case OP_AutoCommit: {
*/
case OP_Transaction: {
Btree *pBt;
+ Db *pDb;
int iMeta = 0;
assert( p->bIsReader );
@@ -93816,11 +92537,20 @@ case OP_Transaction: {
assert( pOp->p2>=0 && pOp->p2<=2 );
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( DbMaskTest(p->btreeMask, pOp->p1) );
- if( pOp->p2 && (db->flags & SQLITE_QueryOnly)!=0 ){
- rc = SQLITE_READONLY;
+ assert( rc==SQLITE_OK );
+ if( pOp->p2 && (db->flags & (SQLITE_QueryOnly|SQLITE_CorruptRdOnly))!=0 ){
+ if( db->flags & SQLITE_QueryOnly ){
+ /* Writes prohibited by the "PRAGMA query_only=TRUE" statement */
+ rc = SQLITE_READONLY;
+ }else{
+ /* Writes prohibited due to a prior SQLITE_CORRUPT in the current
+ ** transaction */
+ rc = SQLITE_CORRUPT;
+ }
goto abort_due_to_error;
}
- pBt = db->aDb[pOp->p1].pBt;
+ pDb = &db->aDb[pOp->p1];
+ pBt = pDb->pBt;
if( pBt ){
rc = sqlcipher_sqlite3BtreeBeginTrans(pBt, pOp->p2, &iMeta);
@@ -93859,9 +92589,9 @@ case OP_Transaction: {
}
}
assert( pOp->p5==0 || pOp->p4type==P4_INT32 );
- if( pOp->p5
- && (iMeta!=pOp->p3
- || db->aDb[pOp->p1].pSchema->iGeneration!=pOp->p4.i)
+ if( rc==SQLITE_OK
+ && pOp->p5
+ && (iMeta!=pOp->p3 || pDb->pSchema->iGeneration!=pOp->p4.i)
){
/*
** IMPLEMENTATION-OF: R-03189-51135 As each SQL statement runs, the schema
@@ -93888,6 +92618,11 @@ case OP_Transaction: {
}
p->expired = 1;
rc = SQLITE_SCHEMA;
+
+ /* Set changeCntOn to 0 to prevent the value returned by sqlcipher_sqlite3_changes()
+ ** from being modified in sqlcipher_sqlite3VdbeHalt(). If this statement is
+ ** reprepared, changeCntOn will be set again. */
+ p->changeCntOn = 0;
}
if( rc ) goto abort_due_to_error;
break;
@@ -93954,8 +92689,9 @@ case OP_SetCookie: {
rc = sqlcipher_sqlite3BtreeUpdateMeta(pDb->pBt, pOp->p2, pOp->p3);
if( pOp->p2==BTREE_SCHEMA_VERSION ){
/* When the schema cookie changes, record the new cookie internally */
- pDb->pSchema->schema_cookie = pOp->p3 - pOp->p5;
+ *(u32*)&pDb->pSchema->schema_cookie = *(u32*)&pOp->p3 - pOp->p5;
db->mDbFlags |= DBFLAG_SchemaChange;
+ sqlcipher_sqlite3FkClearTriggerCache(db, pOp->p1);
}else if( pOp->p2==BTREE_FILE_FORMAT ){
/* Record changes in the file format */
pDb->pSchema->file_format = pOp->p3;
@@ -94069,6 +92805,8 @@ case OP_ReopenIdx: {
pCur = p->apCsr[pOp->p1];
if( pCur && pCur->pgnoRoot==(u32)pOp->p2 ){
assert( pCur->iDb==pOp->p3 ); /* Guaranteed by the code generator */
+ assert( pCur->eCurType==CURTYPE_BTREE );
+ sqlcipher_sqlite3BtreeClearCursor(pCur->uc.pCursor);
goto open_cursor_set_hints;
}
/* If the cursor is not currently open or is open on a different
@@ -94131,8 +92869,9 @@ case OP_OpenWrite:
assert( pOp->p1>=0 );
assert( nField>=0 );
testcase( nField==0 ); /* Table with INTEGER PRIMARY KEY and nothing else */
- pCur = allocateCursor(p, pOp->p1, nField, iDb, CURTYPE_BTREE);
+ pCur = allocateCursor(p, pOp->p1, nField, CURTYPE_BTREE);
if( pCur==0 ) goto no_mem;
+ pCur->iDb = iDb;
pCur->nullRow = 1;
pCur->isOrdered = 1;
pCur->pgnoRoot = p2;
@@ -94172,9 +92911,9 @@ case OP_OpenDup: {
pOrig = p->apCsr[pOp->p2];
assert( pOrig );
- assert( pOrig->pBtx!=0 ); /* Only ephemeral cursors can be duplicated */
+ assert( pOrig->isEphemeral ); /* Only ephemeral cursors can be duplicated */
- pCx = allocateCursor(p, pOp->p1, pOrig->nField, -1, CURTYPE_BTREE);
+ pCx = allocateCursor(p, pOp->p1, pOrig->nField, CURTYPE_BTREE);
if( pCx==0 ) goto no_mem;
pCx->nullRow = 1;
pCx->isEphemeral = 1;
@@ -94182,7 +92921,10 @@ case OP_OpenDup: {
pCx->isTable = pOrig->isTable;
pCx->pgnoRoot = pOrig->pgnoRoot;
pCx->isOrdered = pOrig->isOrdered;
- rc = sqlcipher_sqlite3BtreeCursor(pOrig->pBtx, pCx->pgnoRoot, BTREE_WRCSR,
+ pCx->ub.pBtx = pOrig->ub.pBtx;
+ pCx->noReuse = 1;
+ pOrig->noReuse = 1;
+ rc = sqlcipher_sqlite3BtreeCursor(pCx->ub.pBtx, pCx->pgnoRoot, BTREE_WRCSR,
pCx->pKeyInfo, pCx->uc.pCursor);
/* The sqlcipher_sqlite3BtreeCursor() routine can only fail for the first cursor
** opened for a database. Since there is already an open cursor when this
@@ -94248,49 +92990,53 @@ case OP_OpenEphemeral: {
aMem[pOp->p3].z = "";
}
pCx = p->apCsr[pOp->p1];
- if( pCx && pCx->pBtx ){
- /* If the ephermeral table is already open, erase all existing content
- ** so that the table is empty again, rather than creating a new table. */
+ if( pCx && !pCx->noReuse && ALWAYS(pOp->p2<=pCx->nField) ){
+ /* If the ephermeral table is already open and has no duplicates from
+ ** OP_OpenDup, then erase all existing content so that the table is
+ ** empty again, rather than creating a new table. */
assert( pCx->isEphemeral );
pCx->seqCount = 0;
pCx->cacheStatus = CACHE_STALE;
- rc = sqlcipher_sqlite3BtreeClearTable(pCx->pBtx, pCx->pgnoRoot, 0);
+ rc = sqlcipher_sqlite3BtreeClearTable(pCx->ub.pBtx, pCx->pgnoRoot, 0);
}else{
- pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, CURTYPE_BTREE);
+ pCx = allocateCursor(p, pOp->p1, pOp->p2, CURTYPE_BTREE);
if( pCx==0 ) goto no_mem;
pCx->isEphemeral = 1;
- rc = sqlcipher_sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBtx,
+ rc = sqlcipher_sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->ub.pBtx,
BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5,
vfsFlags);
if( rc==SQLITE_OK ){
- rc = sqlcipher_sqlite3BtreeBeginTrans(pCx->pBtx, 1, 0);
- }
- if( rc==SQLITE_OK ){
- /* If a transient index is required, create it by calling
- ** sqlcipher_sqlite3BtreeCreateTable() with the BTREE_BLOBKEY flag before
- ** opening it. If a transient table is required, just use the
- ** automatically created table with root-page 1 (an BLOB_INTKEY table).
- */
- if( (pCx->pKeyInfo = pKeyInfo = pOp->p4.pKeyInfo)!=0 ){
- assert( pOp->p4type==P4_KEYINFO );
- rc = sqlcipher_sqlite3BtreeCreateTable(pCx->pBtx, &pCx->pgnoRoot,
- BTREE_BLOBKEY | pOp->p5);
- if( rc==SQLITE_OK ){
- assert( pCx->pgnoRoot==SCHEMA_ROOT+1 );
- assert( pKeyInfo->db==db );
- assert( pKeyInfo->enc==ENC(db) );
- rc = sqlcipher_sqlite3BtreeCursor(pCx->pBtx, pCx->pgnoRoot, BTREE_WRCSR,
- pKeyInfo, pCx->uc.pCursor);
+ rc = sqlcipher_sqlite3BtreeBeginTrans(pCx->ub.pBtx, 1, 0);
+ if( rc==SQLITE_OK ){
+ /* If a transient index is required, create it by calling
+ ** sqlcipher_sqlite3BtreeCreateTable() with the BTREE_BLOBKEY flag before
+ ** opening it. If a transient table is required, just use the
+ ** automatically created table with root-page 1 (an BLOB_INTKEY table).
+ */
+ if( (pCx->pKeyInfo = pKeyInfo = pOp->p4.pKeyInfo)!=0 ){
+ assert( pOp->p4type==P4_KEYINFO );
+ rc = sqlcipher_sqlite3BtreeCreateTable(pCx->ub.pBtx, &pCx->pgnoRoot,
+ BTREE_BLOBKEY | pOp->p5);
+ if( rc==SQLITE_OK ){
+ assert( pCx->pgnoRoot==SCHEMA_ROOT+1 );
+ assert( pKeyInfo->db==db );
+ assert( pKeyInfo->enc==ENC(db) );
+ rc = sqlcipher_sqlite3BtreeCursor(pCx->ub.pBtx, pCx->pgnoRoot, BTREE_WRCSR,
+ pKeyInfo, pCx->uc.pCursor);
+ }
+ pCx->isTable = 0;
+ }else{
+ pCx->pgnoRoot = SCHEMA_ROOT;
+ rc = sqlcipher_sqlite3BtreeCursor(pCx->ub.pBtx, SCHEMA_ROOT, BTREE_WRCSR,
+ 0, pCx->uc.pCursor);
+ pCx->isTable = 1;
}
- pCx->isTable = 0;
- }else{
- pCx->pgnoRoot = SCHEMA_ROOT;
- rc = sqlcipher_sqlite3BtreeCursor(pCx->pBtx, SCHEMA_ROOT, BTREE_WRCSR,
- 0, pCx->uc.pCursor);
- pCx->isTable = 1;
+ }
+ pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
+ if( rc ){
+ sqlcipher_sqlite3BtreeClose(pCx->ub.pBtx);
}
}
- pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
}
if( rc ) goto abort_due_to_error;
pCx->nullRow = 1;
@@ -94312,7 +93058,7 @@ case OP_SorterOpen: {
assert( pOp->p1>=0 );
assert( pOp->p2>=0 );
- pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, CURTYPE_SORTER);
+ pCx = allocateCursor(p, pOp->p1, pOp->p2, CURTYPE_SORTER);
if( pCx==0 ) goto no_mem;
pCx->pKeyInfo = pOp->p4.pKeyInfo;
assert( pCx->pKeyInfo->db==db );
@@ -94361,7 +93107,7 @@ case OP_OpenPseudo: {
assert( pOp->p1>=0 );
assert( pOp->p3>=0 );
- pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, CURTYPE_PSEUDO);
+ pCx = allocateCursor(p, pOp->p1, pOp->p3, CURTYPE_PSEUDO);
if( pCx==0 ) goto no_mem;
pCx->nullRow = 1;
pCx->seekResult = pOp->p2;
@@ -94549,6 +93295,7 @@ case OP_SeekGT: { /* jump, in3, group */
/* If the P3 value could not be converted into an integer without
** loss of information, then special processing is required... */
if( (newType & (MEM_Int|MEM_IntReal))==0 ){
+ int c;
if( (newType & MEM_Real)==0 ){
if( (newType & MEM_Null) || oc>=OP_SeekGE ){
VdbeBranchTaken(1,2);
@@ -94558,7 +93305,8 @@ case OP_SeekGT: { /* jump, in3, group */
if( rc!=SQLITE_OK ) goto abort_due_to_error;
goto seek_not_found;
}
- }else
+ }
+ c = sqlcipher_sqlite3IntFloatCompare(iKey, pIn3->u.r);
/* If the approximation iKey is larger than the actual real search
** term, substitute >= for > and < for <=. e.g. if the search term
@@ -94567,7 +93315,7 @@ case OP_SeekGT: { /* jump, in3, group */
** (x > 4.9) -> (x >= 5)
** (x <= 4.9) -> (x < 5)
*/
- if( pIn3->u.r<(double)iKey ){
+ if( c>0 ){
assert( OP_SeekGE==(OP_SeekGT-1) );
assert( OP_SeekLT==(OP_SeekLE-1) );
assert( (OP_SeekLE & 0x0001)==(OP_SeekGT & 0x0001) );
@@ -94576,14 +93324,14 @@ case OP_SeekGT: { /* jump, in3, group */
/* If the approximation iKey is smaller than the actual real search
** term, substitute <= for < and > for >=. */
- else if( pIn3->u.r>(double)iKey ){
+ else if( c<0 ){
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++;
}
}
- rc = sqlcipher_sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, 0, (u64)iKey, 0, &res);
+ rc = sqlcipher_sqlite3BtreeTableMoveto(pC->uc.pCursor, (u64)iKey, 0, &res);
pC->movetoTarget = iKey; /* Used by OP_Delete */
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
@@ -94630,7 +93378,7 @@ case OP_SeekGT: { /* jump, in3, group */
{ int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
#endif
r.eqSeen = 0;
- rc = sqlcipher_sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, &r, 0, 0, &res);
+ rc = sqlcipher_sqlite3BtreeIndexMoveto(pC->uc.pCursor, &r, &res);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
@@ -94724,13 +93472,13 @@ seek_not_found:
**
** There are three possible outcomes from this opcode:<ol>
**
-** <li> If after This.P1 steps, the cursor is still point to a place that
-** is earlier in the btree than the target row,
-** then fall through into the subsquence OP_SeekGE opcode.
+** <li> If after This.P1 steps, the cursor is still pointing to a place that
+** is earlier in the btree than the target row, then fall through
+** into the subsquence OP_SeekGE opcode.
**
** <li> If the cursor is successfully moved to the target row by 0 or more
** sqlcipher_sqlite3BtreeNext() calls, then jump to This.P2, which will land just
-** past the OP_IdxGT opcode that follows the OP_SeekGE.
+** past the OP_IdxGT or OP_IdxGE opcode that follows the OP_SeekGE.
**
** <li> If the cursor ends up past the target row (indicating the the target
** row does not exist in the btree) then jump to SeekOP.P2.
@@ -94747,7 +93495,8 @@ case OP_SeekScan: {
/* pOp->p2 points to the first instruction past the OP_IdxGT that
** follows the OP_SeekGE. */
assert( pOp->p2>=(int)(pOp-aOp)+2 );
- assert( aOp[pOp->p2-1].opcode==OP_IdxGT );
+ assert( aOp[pOp->p2-1].opcode==OP_IdxGT || aOp[pOp->p2-1].opcode==OP_IdxGE );
+ testcase( aOp[pOp->p2-1].opcode==OP_IdxGE );
assert( pOp[1].p1==aOp[pOp->p2-1].p1 );
assert( pOp[1].p2==aOp[pOp->p2-1].p2 );
assert( pOp[1].p3==aOp[pOp->p2-1].p3 );
@@ -94851,8 +93600,18 @@ case OP_SeekHit: {
assert( pC!=0 );
assert( pOp->p3>=pOp->p2 );
if( pC->seekHit<pOp->p2 ){
+#ifdef SQLITE_DEBUG
+ if( db->flags&SQLITE_VdbeTrace ){
+ printf("seekHit changes from %d to %d\n", pC->seekHit, pOp->p2);
+ }
+#endif
pC->seekHit = pOp->p2;
}else if( pC->seekHit>pOp->p3 ){
+#ifdef SQLITE_DEBUG
+ if( db->flags&SQLITE_VdbeTrace ){
+ printf("seekHit changes from %d to %d\n", pC->seekHit, pOp->p3);
+ }
+#endif
pC->seekHit = pOp->p3;
}
break;
@@ -94967,6 +93726,11 @@ case OP_IfNoHope: { /* jump, in3 */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
+#ifdef SQLITE_DEBUG
+ if( db->flags&SQLITE_VdbeTrace ){
+ printf("seekHit is %d\n", pC->seekHit);
+ }
+#endif
if( pC->seekHit>=pOp->p4.i ) break;
/* Fall through into OP_NotFound */
/* no break */ deliberate_fall_through
@@ -94975,11 +93739,8 @@ case OP_NoConflict: /* jump, in3 */
case OP_NotFound: /* jump, in3 */
case OP_Found: { /* jump, in3 */
int alreadyExists;
- int takeJump;
int ii;
VdbeCursor *pC;
- int res;
- UnpackedRecord *pFree;
UnpackedRecord *pIdxKey;
UnpackedRecord r;
@@ -94994,14 +93755,15 @@ case OP_Found: { /* jump, in3 */
#ifdef SQLITE_DEBUG
pC->seekOp = pOp->opcode;
#endif
- pIn3 = &aMem[pOp->p3];
+ r.aMem = &aMem[pOp->p3];
assert( pC->eCurType==CURTYPE_BTREE );
assert( pC->uc.pCursor!=0 );
assert( pC->isTable==0 );
- if( pOp->p4.i>0 ){
+ r.nField = (u16)pOp->p4.i;
+ if( r.nField>0 ){
+ /* Key values in an array of registers */
r.pKeyInfo = pC->pKeyInfo;
- r.nField = (u16)pOp->p4.i;
- r.aMem = pIn3;
+ r.default_rc = 0;
#ifdef SQLITE_DEBUG
for(ii=0; ii<r.nField; ii++){
assert( memIsValid(&r.aMem[ii]) );
@@ -95009,37 +93771,25 @@ case OP_Found: { /* jump, in3 */
if( ii ) REGISTER_TRACE(pOp->p3+ii, &r.aMem[ii]);
}
#endif
- pIdxKey = &r;
- pFree = 0;
+ rc = sqlcipher_sqlite3BtreeIndexMoveto(pC->uc.pCursor, &r, &pC->seekResult);
}else{
- assert( pIn3->flags & MEM_Blob );
- rc = ExpandBlob(pIn3);
+ /* Composite key generated by OP_MakeRecord */
+ assert( r.aMem->flags & MEM_Blob );
+ assert( pOp->opcode!=OP_NoConflict );
+ rc = ExpandBlob(r.aMem);
assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
if( rc ) goto no_mem;
- pFree = pIdxKey = sqlcipher_sqlite3VdbeAllocUnpackedRecord(pC->pKeyInfo);
+ pIdxKey = sqlcipher_sqlite3VdbeAllocUnpackedRecord(pC->pKeyInfo);
if( pIdxKey==0 ) goto no_mem;
- sqlcipher_sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z, pIdxKey);
+ sqlcipher_sqlite3VdbeRecordUnpack(pC->pKeyInfo, r.aMem->n, r.aMem->z, pIdxKey);
+ pIdxKey->default_rc = 0;
+ rc = sqlcipher_sqlite3BtreeIndexMoveto(pC->uc.pCursor, pIdxKey, &pC->seekResult);
+ sqlcipher_sqlite3DbFreeNN(db, pIdxKey);
}
- pIdxKey->default_rc = 0;
- takeJump = 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<pIdxKey->nField; ii++){
- if( pIdxKey->aMem[ii].flags & MEM_Null ){
- takeJump = 1;
- break;
- }
- }
- }
- rc = sqlcipher_sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, pIdxKey, 0, 0, &res);
- if( pFree ) sqlcipher_sqlite3DbFreeNN(db, pFree);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
- pC->seekResult = res;
- alreadyExists = (res==0);
+ alreadyExists = (pC->seekResult==0);
pC->nullRow = 1-alreadyExists;
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
@@ -95047,9 +93797,25 @@ case OP_Found: { /* jump, in3 */
VdbeBranchTaken(alreadyExists!=0,2);
if( alreadyExists ) goto jump_to_p2;
}else{
- VdbeBranchTaken(takeJump||alreadyExists==0,2);
- if( takeJump || !alreadyExists ) goto jump_to_p2;
- if( pOp->opcode==OP_IfNoHope ) pC->seekHit = pOp->p4.i;
+ if( !alreadyExists ){
+ VdbeBranchTaken(1,2);
+ goto jump_to_p2;
+ }
+ 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 ){
+ VdbeBranchTaken(1,2);
+ goto jump_to_p2;
+ }
+ }
+ }
+ VdbeBranchTaken(0,2);
+ if( pOp->opcode==OP_IfNoHope ){
+ pC->seekHit = pOp->p4.i;
+ }
}
break;
}
@@ -95142,7 +93908,7 @@ notExistsWithKey:
pCrsr = pC->uc.pCursor;
assert( pCrsr!=0 );
res = 0;
- rc = sqlcipher_sqlite3BtreeMovetoUnpacked(pCrsr, 0, iKey, 0, &res);
+ rc = sqlcipher_sqlite3BtreeTableMoveto(pCrsr, iKey, 0, &res);
assert( rc==SQLITE_OK || res==0 );
pC->movetoTarget = iKey; /* Used by OP_Delete */
pC->nullRow = 0;
@@ -95200,8 +93966,10 @@ case OP_NewRowid: { /* out2 */
VdbeCursor *pC; /* Cursor of table to get the new rowid */
int res; /* Result of an sqlcipher_sqlite3BtreeLast() */
int cnt; /* Counter to limit the number of searches */
+#ifndef SQLITE_OMIT_AUTOINCREMENT
Mem *pMem; /* Register holding largest rowid for AUTOINCREMENT */
VdbeFrame *pFrame; /* Root frame of VDBE */
+#endif
v = 0;
res = 0;
@@ -95297,7 +94065,7 @@ case OP_NewRowid: { /* out2 */
do{
sqlcipher_sqlite3_randomness(sizeof(v), &v);
v &= (MAX_ROWID>>1); v++; /* Ensure that v is greater than zero */
- }while( ((rc = sqlcipher_sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, 0, (u64)v,
+ }while( ((rc = sqlcipher_sqlite3BtreeTableMoveto(pC->uc.pCursor, (u64)v,
0, &res))==SQLITE_OK)
&& (res==0)
&& (++cnt<100));
@@ -95387,14 +94155,14 @@ case OP_Insert: {
assert( (pOp->p5 & OPFLAG_ISNOOP) || HasRowid(pTab) );
}else{
pTab = 0;
- zDb = 0; /* Not needed. Silence a compiler warning. */
+ zDb = 0;
}
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
/* Invoke the pre-update hook, if any */
if( pTab ){
if( db->xPreUpdateCallback && !(pOp->p5 & OPFLAG_ISUPDATE) ){
- sqlcipher_sqlite3VdbePreUpdateHook(p, pC, SQLITE_INSERT, zDb, pTab, x.nKey,pOp->p2);
+ sqlcipher_sqlite3VdbePreUpdateHook(p,pC,SQLITE_INSERT,zDb,pTab,x.nKey,pOp->p2,-1);
}
if( db->xUpdateCallback==0 || pTab->aCol==0 ){
/* Prevent post-update hook from running in cases when it should not */
@@ -95417,7 +94185,8 @@ case OP_Insert: {
}
x.pKey = 0;
rc = sqlcipher_sqlite3BtreeInsert(pC->uc.pCursor, &x,
- (pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION)), seekResult
+ (pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION|OPFLAG_PREFORMAT)),
+ seekResult
);
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
@@ -95434,6 +94203,33 @@ case OP_Insert: {
break;
}
+/* Opcode: RowCell P1 P2 P3 * *
+**
+** P1 and P2 are both open cursors. Both must be opened on the same type
+** of table - intkey or index. This opcode is used as part of copying
+** the current row from P2 into P1. If the cursors are opened on intkey
+** tables, register P3 contains the rowid to use with the new record in
+** P1. If they are opened on index tables, P3 is not used.
+**
+** This opcode must be followed by either an Insert or InsertIdx opcode
+** with the OPFLAG_PREFORMAT flag set to complete the insert operation.
+*/
+case OP_RowCell: {
+ VdbeCursor *pDest; /* Cursor to write to */
+ VdbeCursor *pSrc; /* Cursor to read from */
+ i64 iKey; /* Rowid value to insert with */
+ assert( pOp[1].opcode==OP_Insert || pOp[1].opcode==OP_IdxInsert );
+ assert( pOp[1].opcode==OP_Insert || pOp->p3==0 );
+ assert( pOp[1].opcode==OP_IdxInsert || pOp->p3>0 );
+ assert( pOp[1].p5 & OPFLAG_PREFORMAT );
+ pDest = p->apCsr[pOp->p1];
+ pSrc = p->apCsr[pOp->p2];
+ iKey = pOp->p3 ? aMem[pOp->p3].u.i : 0;
+ rc = sqlcipher_sqlite3BtreeTransferRow(pDest->uc.pCursor, pSrc->uc.pCursor, iKey);
+ if( rc!=SQLITE_OK ) goto abort_due_to_error;
+ break;
+};
+
/* Opcode: Delete P1 P2 P3 P4 P5
**
** Delete the record at which the P1 cursor is currently pointing.
@@ -95512,13 +94308,14 @@ case OP_Delete: {
pC->movetoTarget = sqlcipher_sqlite3BtreeIntegerKey(pC->uc.pCursor);
}
}else{
- zDb = 0; /* Not needed. Silence a compiler warning. */
- pTab = 0; /* Not needed. Silence a compiler warning. */
+ zDb = 0;
+ pTab = 0;
}
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
/* Invoke the pre-update-hook if required. */
- if( db->xPreUpdateCallback && pOp->p4.pTab ){
+ assert( db->xPreUpdateCallback==0 || pTab==pOp->p4.pTab );
+ if( db->xPreUpdateCallback && pTab ){
assert( !(opflags & OPFLAG_ISUPDATE)
|| HasRowid(pTab)==0
|| (aMem[pOp->p3].flags & MEM_Int)
@@ -95526,7 +94323,7 @@ case OP_Delete: {
sqlcipher_sqlite3VdbePreUpdateHook(p, pC,
(opflags & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_DELETE,
zDb, pTab, pC->movetoTarget,
- pOp->p3
+ pOp->p3, -1
);
}
if( opflags & OPFLAG_ISNOOP ) break;
@@ -95559,7 +94356,7 @@ case OP_Delete: {
/* Invoke the update-hook if required. */
if( opflags & OPFLAG_NCHANGE ){
p->nChange++;
- if( db->xUpdateCallback && HasRowid(pTab) ){
+ if( db->xUpdateCallback && ALWAYS(pTab!=0) && HasRowid(pTab) ){
db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, pTab->zName,
pC->movetoTarget);
assert( pC->iDb>=0 );
@@ -95709,7 +94506,7 @@ case OP_RowData: {
}
/* Opcode: Rowid P1 P2 * * *
-** Synopsis: r[P2]=rowid
+** Synopsis: r[P2]=PX rowid of P1
**
** Store in register P2 an integer which is the key of the table entry that
** P1 is currently point to.
@@ -95764,13 +94561,25 @@ case OP_Rowid: { /* out2 */
** Move the cursor P1 to a null row. Any OP_Column operations
** that occur while the cursor is on the null row will always
** write a NULL.
+**
+** If cursor P1 is not previously opened, open it now to a special
+** pseudo-cursor that always returns NULL for every column.
*/
case OP_NullRow: {
VdbeCursor *pC;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
- assert( pC!=0 );
+ if( pC==0 ){
+ /* If the cursor is not already open, create a special kind of
+ ** pseudo-cursor that always gives null rows. */
+ pC = allocateCursor(p, pOp->p1, 1, CURTYPE_PSEUDO);
+ if( pC==0 ) goto no_mem;
+ pC->seekResult = 0;
+ pC->isTable = 1;
+ pC->noReuse = 1;
+ pC->uc.pCursor = sqlcipher_sqlite3BtreeFakeValidCursor();
+ }
pC->nullRow = 1;
pC->cacheStatus = CACHE_STALE;
if( pC->eCurType==CURTYPE_BTREE ){
@@ -95943,7 +94752,7 @@ case OP_Rewind: { /* jump */
break;
}
-/* Opcode: Next P1 P2 P3 P4 P5
+/* Opcode: Next P1 P2 P3 * 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
@@ -95962,15 +94771,12 @@ case OP_Rewind: { /* jump */
** 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
-** sqlcipher_sqlite3BtreeNext().
-**
** If P5 is positive and the jump is taken, then event counter
** number P5-1 in the prepared statement is incremented.
**
** See also: Prev
*/
-/* Opcode: Prev P1 P2 P3 P4 P5
+/* Opcode: Prev P1 P2 P3 * 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
@@ -95990,9 +94796,6 @@ case OP_Rewind: { /* jump */
** 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
-** sqlcipher_sqlite3BtreePrevious().
-**
** If P5 is positive and the jump is taken, then event counter
** number P5-1 in the prepared statement is incremented.
*/
@@ -96010,30 +94813,33 @@ case OP_SorterNext: { /* jump */
assert( isSorter(pC) );
rc = sqlcipher_sqlite3VdbeSorterNext(db, pC);
goto next_tail;
+
case OP_Prev: /* jump */
-case OP_Next: /* jump */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
assert( pOp->p5<ArraySize(p->aCounter) );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
assert( pC->deferredMoveto==0 );
assert( pC->eCurType==CURTYPE_BTREE );
- assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlcipher_sqlite3BtreeNext );
- assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlcipher_sqlite3BtreePrevious );
+ assert( pC->seekOp==OP_SeekLT || pC->seekOp==OP_SeekLE
+ || pC->seekOp==OP_Last || pC->seekOp==OP_IfNoHope
+ || pC->seekOp==OP_NullRow);
+ rc = sqlcipher_sqlite3BtreePrevious(pC->uc.pCursor, pOp->p3);
+ goto next_tail;
- /* The Next opcode is only used after SeekGT, SeekGE, Rewind, and Found.
- ** The Prev opcode is only used after SeekLT, SeekLE, and Last. */
- assert( pOp->opcode!=OP_Next
- || pC->seekOp==OP_SeekGT || pC->seekOp==OP_SeekGE
+case OP_Next: /* jump */
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
+ assert( pOp->p5<ArraySize(p->aCounter) );
+ pC = p->apCsr[pOp->p1];
+ assert( pC!=0 );
+ assert( pC->deferredMoveto==0 );
+ assert( pC->eCurType==CURTYPE_BTREE );
+ assert( pC->seekOp==OP_SeekGT || pC->seekOp==OP_SeekGE
|| pC->seekOp==OP_Rewind || pC->seekOp==OP_Found
|| pC->seekOp==OP_NullRow|| pC->seekOp==OP_SeekRowid
|| pC->seekOp==OP_IfNoHope);
- assert( pOp->opcode!=OP_Prev
- || pC->seekOp==OP_SeekLT || pC->seekOp==OP_SeekLE
- || pC->seekOp==OP_Last || pC->seekOp==OP_IfNoHope
- || pC->seekOp==OP_NullRow);
+ rc = sqlcipher_sqlite3BtreeNext(pC->uc.pCursor, pOp->p3);
- rc = pOp->p4.xAdvance(pC->uc.pCursor, pOp->p3);
next_tail:
pC->cacheStatus = CACHE_STALE;
VdbeBranchTaken(rc==SQLITE_OK,2);
@@ -96089,7 +94895,7 @@ case OP_IdxInsert: { /* in2 */
assert( pC!=0 );
assert( !isSorter(pC) );
pIn2 = &aMem[pOp->p2];
- assert( pIn2->flags & MEM_Blob );
+ assert( (pIn2->flags & MEM_Blob) || (pOp->p5 & OPFLAG_PREFORMAT) );
if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
assert( pC->eCurType==CURTYPE_BTREE );
assert( pC->isTable==0 );
@@ -96100,7 +94906,7 @@ case OP_IdxInsert: { /* in2 */
x.aMem = aMem + pOp->p3;
x.nMem = (u16)pOp->p4.i;
rc = sqlcipher_sqlite3BtreeInsert(pC->uc.pCursor, &x,
- (pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION)),
+ (pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION|OPFLAG_PREFORMAT)),
((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0)
);
assert( pC->deferredMoveto==0 );
@@ -96146,7 +94952,8 @@ case OP_SorterInsert: { /* in2 */
** an UPDATE or DELETE statement and the index entry to be updated
** or deleted is not found. For some uses of IdxDelete
** (example: the EXCEPT operator) it does not matter that no matching
-** entry is found. For those cases, P5 is zero.
+** entry is found. For those cases, P5 is zero. Also, do not raise
+** this (self-correcting and non-critical) error if in writable_schema mode.
*/
case OP_IdxDelete: {
VdbeCursor *pC;
@@ -96167,13 +94974,13 @@ case OP_IdxDelete: {
r.nField = (u16)pOp->p3;
r.default_rc = 0;
r.aMem = &aMem[pOp->p2];
- rc = sqlcipher_sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, 0, &res);
+ rc = sqlcipher_sqlite3BtreeIndexMoveto(pCrsr, &r, &res);
if( rc ) goto abort_due_to_error;
if( res==0 ){
rc = sqlcipher_sqlite3BtreeDelete(pCrsr, BTREE_AUXDELETE);
if( rc ) goto abort_due_to_error;
- }else if( pOp->p5 ){
- rc = SQLITE_CORRUPT_INDEX;
+ }else if( pOp->p5 && !sqlcipher_sqlite3WritableSchema(db) ){
+ rc = sqlcipher_sqlite3ReportError(SQLITE_CORRUPT_INDEX, __LINE__, "index corruption");
goto abort_due_to_error;
}
assert( pC->deferredMoveto==0 );
@@ -96219,9 +95026,9 @@ case OP_IdxRowid: { /* out2 */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
- assert( pC->eCurType==CURTYPE_BTREE );
+ assert( pC->eCurType==CURTYPE_BTREE || IsNullCursor(pC) );
assert( pC->uc.pCursor!=0 );
- assert( pC->isTable==0 );
+ assert( pC->isTable==0 || IsNullCursor(pC) );
assert( pC->deferredMoveto==0 );
assert( !pC->nullRow || pOp->opcode==OP_IdxRowid );
@@ -96250,8 +95057,11 @@ case OP_IdxRowid: { /* out2 */
pTabCur->nullRow = 0;
pTabCur->movetoTarget = rowid;
pTabCur->deferredMoveto = 1;
+ pTabCur->cacheStatus = CACHE_STALE;
assert( pOp->p4type==P4_INTARRAY || pOp->p4.ai==0 );
- pTabCur->aAltMap = pOp->p4.ai;
+ assert( !pTabCur->isEphemeral );
+ pTabCur->ub.aAltMap = pOp->p4.ai;
+ assert( !pC->isEphemeral );
pTabCur->pAltCursor = pC;
}else{
pOut = out2Prerelease(p, pOp);
@@ -96382,7 +95192,7 @@ case OP_IdxGE: { /* jump */
rc = sqlcipher_sqlite3VdbeMemFromBtreeZeroOffset(pCur, (u32)nCellKey, &m);
if( rc ) goto abort_due_to_error;
res = sqlcipher_sqlite3VdbeRecordCompareWithSkip(m.n, m.z, &r, 0);
- sqlcipher_sqlite3VdbeMemRelease(&m);
+ sqlcipher_sqlite3VdbeMemReleaseMalloc(&m);
}
/* End of inlined sqlcipher_sqlite3VdbeIdxKeyCompare() */
@@ -96470,24 +95280,21 @@ case OP_Destroy: { /* out2 */
** P2==1 then the table to be clear is in the auxiliary database file
** that is used to store tables create using CREATE TEMPORARY TABLE.
**
-** If the P3 value is non-zero, then the table referred to must be an
-** intkey table (an SQL table, not an index). In this case the row change
-** count is incremented by the number of rows in the table being cleared.
-** If P3 is greater than zero, then the value stored in register P3 is
-** also incremented by the number of rows in the table being cleared.
+** If the P3 value is non-zero, then the row change count is incremented
+** by the number of rows in the table being cleared. If P3 is greater
+** than zero, then the value stored in register P3 is also incremented
+** by the number of rows in the table being cleared.
**
** See also: Destroy
*/
case OP_Clear: {
- int nChange;
+ i64 nChange;
sqlcipher_sqlite3VdbeIncrWriteCounter(p, 0);
nChange = 0;
assert( p->readOnly==0 );
assert( DbMaskTest(p->btreeMask, pOp->p2) );
- rc = sqlcipher_sqlite3BtreeClearTable(
- db->aDb[pOp->p2].pBt, (u32)pOp->p1, (pOp->p3 ? &nChange : 0)
- );
+ rc = sqlcipher_sqlite3BtreeClearTable(db->aDb[pOp->p2].pBt, (u32)pOp->p1, &nChange);
if( pOp->p3 ){
p->nChange += nChange;
if( pOp->p3>0 ){
@@ -96593,19 +95400,21 @@ case OP_ParseSchema: {
iDb = pOp->p1;
assert( iDb>=0 && iDb<db->nDb );
- assert( DbHasProperty(db, iDb, DB_SchemaLoaded) );
+ assert( DbHasProperty(db, iDb, DB_SchemaLoaded)
+ || db->mallocFailed
+ || (CORRUPT_DB && (db->flags & SQLITE_NoSchemaError)!=0) );
#ifndef SQLITE_OMIT_ALTERTABLE
if( pOp->p4.z==0 ){
sqlcipher_sqlite3SchemaClear(db->aDb[iDb].pSchema);
db->mDbFlags &= ~DBFLAG_SchemaKnownOk;
- rc = sqlcipher_sqlite3InitOne(db, iDb, &p->zErrMsg, INITFLAG_AlterTable);
+ rc = sqlcipher_sqlite3InitOne(db, iDb, &p->zErrMsg, pOp->p5);
db->mDbFlags |= DBFLAG_SchemaChange;
p->expired = 0;
}else
#endif
{
- zSchema = DFLT_SCHEMA_TABLE;
+ zSchema = LEGACY_SCHEMA_TABLE;
initData.db = db;
initData.iDb = iDb;
initData.pzErrMsg = &p->zErrMsg;
@@ -97264,6 +96073,7 @@ case OP_AggStep: {
pCtx->pVdbe = p;
pCtx->skipFlag = 0;
pCtx->isError = 0;
+ pCtx->enc = encoding;
pCtx->argc = n;
pOp->p4type = P4_FUNCCTX;
pOp->p4.pCtx = pCtx;
@@ -97393,9 +96203,6 @@ case OP_AggFinal: {
}
sqlcipher_sqlite3VdbeChangeEncoding(pMem, encoding);
UPDATE_MAX_BLOBSIZE(pMem);
- if( sqlcipher_sqlite3VdbeMemTooBig(pMem) ){
- goto too_big;
- }
break;
}
@@ -97475,6 +96282,7 @@ case OP_JournalMode: { /* out2 */
pPager = sqlcipher_sqlite3BtreePager(pBt);
eOld = sqlcipher_sqlite3PagerGetJournalMode(pPager);
if( eNew==PAGER_JOURNALMODE_QUERY ) eNew = eOld;
+ assert( sqlcipher_sqlite3BtreeHoldsMutex(pBt) );
if( !sqlcipher_sqlite3PagerOkToChangeJournalMode(pPager) ) eNew = eOld;
#ifndef SQLITE_OMIT_WAL
@@ -97773,7 +96581,7 @@ case OP_VOpen: {
pVCur->pVtab = pVtab;
/* Initialize vdbe cursor object */
- pCur = allocateCursor(p, pOp->p1, 0, -1, CURTYPE_VTAB);
+ pCur = allocateCursor(p, pOp->p1, 0, CURTYPE_VTAB);
if( pCur ){
pCur->uc.pVCur = pVCur;
pVtab->nRef++;
@@ -97787,6 +96595,34 @@ case OP_VOpen: {
#endif /* SQLITE_OMIT_VIRTUALTABLE */
#ifndef SQLITE_OMIT_VIRTUALTABLE
+/* Opcode: VInitIn P1 P2 P3 * *
+** Synopsis: r[P2]=ValueList(P1,P3)
+**
+** Set register P2 to be a pointer to a ValueList object for cursor P1
+** with cache register P3 and output register P3+1. This ValueList object
+** can be used as the first argument to sqlcipher_sqlite3_vtab_in_first() and
+** sqlcipher_sqlite3_vtab_in_next() to extract all of the values stored in the P1
+** cursor. Register P3 is used to hold the values returned by
+** sqlcipher_sqlite3_vtab_in_first() and sqlcipher_sqlite3_vtab_in_next().
+*/
+case OP_VInitIn: { /* out2 */
+ VdbeCursor *pC; /* The cursor containing the RHS values */
+ ValueList *pRhs; /* New ValueList object to put in reg[P2] */
+
+ pC = p->apCsr[pOp->p1];
+ pRhs = sqlcipher_sqlite3_malloc64( sizeof(*pRhs) );
+ if( pRhs==0 ) goto no_mem;
+ pRhs->pCsr = pC->uc.pCursor;
+ pRhs->pOut = &aMem[pOp->p3];
+ pOut = out2Prerelease(p, pOp);
+ pOut->flags = MEM_Null;
+ sqlcipher_sqlite3VdbeMemSetPointer(pOut, pRhs, "ValueList", sqlcipher_sqlite3_free);
+ break;
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VFilter P1 P2 P3 P4 *
** Synopsis: iplan=r[P3] zplan='P4'
**
@@ -97824,6 +96660,7 @@ case OP_VFilter: { /* jump */
pCur = p->apCsr[pOp->p1];
assert( memIsValid(pQuery) );
REGISTER_TRACE(pOp->p3, pQuery);
+ assert( pCur!=0 );
assert( pCur->eCurType==CURTYPE_VTAB );
pVCur = pCur->uc.pVCur;
pVtab = pVCur->pVtab;
@@ -97835,7 +96672,6 @@ case OP_VFilter: { /* jump */
iQuery = (int)pQuery->u.i;
/* Invoke the xFilter method */
- res = 0;
apArg = p->apArg;
for(i = 0; i<nArg; i++){
apArg[i] = &pArgc[i+1];
@@ -97873,7 +96709,7 @@ case OP_VColumn: {
sqlcipher_sqlite3_context sContext;
VdbeCursor *pCur = p->apCsr[pOp->p1];
- assert( pCur->eCurType==CURTYPE_VTAB );
+ assert( pCur!=0 );
assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
pDest = &aMem[pOp->p3];
memAboutToChange(p, pDest);
@@ -97881,11 +96717,13 @@ case OP_VColumn: {
sqlcipher_sqlite3VdbeMemSetNull(pDest);
break;
}
+ assert( pCur->eCurType==CURTYPE_VTAB );
pVtab = pCur->uc.pVCur->pVtab;
pModule = pVtab->pModule;
assert( pModule->xColumn );
memset(&sContext, 0, sizeof(sContext));
sContext.pOut = pDest;
+ sContext.enc = encoding;
assert( pOp->p5==OPFLAG_NOCHNG || pOp->p5==0 );
if( pOp->p5 & OPFLAG_NOCHNG ){
sqlcipher_sqlite3VdbeMemSetNull(pDest);
@@ -97904,9 +96742,6 @@ case OP_VColumn: {
REGISTER_TRACE(pOp->p3, pDest);
UPDATE_MAX_BLOBSIZE(pDest);
- if( sqlcipher_sqlite3VdbeMemTooBig(pDest) ){
- goto too_big;
- }
if( rc ) goto abort_due_to_error;
break;
}
@@ -97925,8 +96760,8 @@ case OP_VNext: { /* jump */
int res;
VdbeCursor *pCur;
- res = 0;
pCur = p->apCsr[pOp->p1];
+ assert( pCur!=0 );
assert( pCur->eCurType==CURTYPE_VTAB );
if( pCur->nullRow ){
break;
@@ -98022,7 +96857,7 @@ case OP_VUpdate: {
const sqlcipher_sqlite3_module *pModule;
int nArg;
int i;
- sqlite_int64 rowid;
+ sqlite_int64 rowid = 0;
Mem **apArg;
Mem *pX;
@@ -98173,6 +97008,7 @@ case OP_Function: { /* group */
if( pCtx->pOut != pOut ){
pCtx->pVdbe = p;
pCtx->pOut = pOut;
+ pCtx->enc = encoding;
for(i=pCtx->argc-1; i>=0; i--) pCtx->argv[i] = &aMem[pOp->p2+i];
}
assert( pCtx->pVdbe==p );
@@ -98199,17 +97035,98 @@ case OP_Function: { /* group */
if( rc ) goto abort_due_to_error;
}
- /* Copy the result of the function into register P3 */
- if( pOut->flags & (MEM_Str|MEM_Blob) ){
- sqlcipher_sqlite3VdbeChangeEncoding(pOut, encoding);
- if( sqlcipher_sqlite3VdbeMemTooBig(pOut) ) goto too_big;
- }
+ assert( (pOut->flags&MEM_Str)==0
+ || pOut->enc==encoding
+ || db->mallocFailed );
+ assert( !sqlcipher_sqlite3VdbeMemTooBig(pOut) );
REGISTER_TRACE(pOp->p3, pOut);
UPDATE_MAX_BLOBSIZE(pOut);
break;
}
+/* Opcode: ClrSubtype P1 * * * *
+** Synopsis: r[P1].subtype = 0
+**
+** Clear the subtype from register P1.
+*/
+case OP_ClrSubtype: { /* in1 */
+ pIn1 = &aMem[pOp->p1];
+ pIn1->flags &= ~MEM_Subtype;
+ break;
+}
+
+/* Opcode: FilterAdd P1 * P3 P4 *
+** Synopsis: filter(P1) += key(P3@P4)
+**
+** Compute a hash on the P4 registers starting with r[P3] and
+** add that hash to the bloom filter contained in r[P1].
+*/
+case OP_FilterAdd: {
+ u64 h;
+
+ assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) );
+ pIn1 = &aMem[pOp->p1];
+ assert( pIn1->flags & MEM_Blob );
+ assert( pIn1->n>0 );
+ h = filterHash(aMem, pOp);
+#ifdef SQLITE_DEBUG
+ if( db->flags&SQLITE_VdbeTrace ){
+ int ii;
+ for(ii=pOp->p3; ii<pOp->p3+pOp->p4.i; ii++){
+ registerTrace(ii, &aMem[ii]);
+ }
+ printf("hash: %llu modulo %d -> %u\n", h, pIn1->n, (int)(h%pIn1->n));
+ }
+#endif
+ h %= pIn1->n;
+ pIn1->z[h/8] |= 1<<(h&7);
+ break;
+}
+
+/* Opcode: Filter P1 P2 P3 P4 *
+** Synopsis: if key(P3@P4) not in filter(P1) goto P2
+**
+** Compute a hash on the key contained in the P4 registers starting
+** with r[P3]. Check to see if that hash is found in the
+** bloom filter hosted by register P1. If it is not present then
+** maybe jump to P2. Otherwise fall through.
+**
+** False negatives are harmless. It is always safe to fall through,
+** even if the value is in the bloom filter. A false negative causes
+** more CPU cycles to be used, but it should still yield the correct
+** answer. However, an incorrect answer may well arise from a
+** false positive - if the jump is taken when it should fall through.
+*/
+case OP_Filter: { /* jump */
+ u64 h;
+
+ assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) );
+ pIn1 = &aMem[pOp->p1];
+ assert( (pIn1->flags & MEM_Blob)!=0 );
+ assert( pIn1->n >= 1 );
+ h = filterHash(aMem, pOp);
+#ifdef SQLITE_DEBUG
+ if( db->flags&SQLITE_VdbeTrace ){
+ int ii;
+ for(ii=pOp->p3; ii<pOp->p3+pOp->p4.i; ii++){
+ registerTrace(ii, &aMem[ii]);
+ }
+ printf("hash: %llu modulo %d -> %u\n", h, pIn1->n, (int)(h%pIn1->n));
+ }
+#endif
+ h %= pIn1->n;
+ if( (pIn1->z[h/8] & (1<<(h&7)))==0 ){
+ VdbeBranchTaken(1, 2);
+ p->aCounter[SQLITE_STMTSTATUS_FILTER_HIT]++;
+ goto jump_to_p2;
+ }else{
+ p->aCounter[SQLITE_STMTSTATUS_FILTER_MISS]++;
+ VdbeBranchTaken(0, 2);
+ }
+ break;
+}
+
/* Opcode: Trace P1 P2 * P4 *
**
** Write P4 on the statement trace output if statement tracing is
@@ -98258,7 +97175,7 @@ case OP_Init: { /* jump */
#ifndef SQLITE_OMIT_TRACE
if( (db->mTrace & (SQLITE_TRACE_STMT|SQLITE_TRACE_LEGACY))!=0
- && !p->doingRerun
+ && p->minWriteFileFormat!=254 /* tag-20220401a */
&& (zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0
){
#ifndef SQLITE_OMIT_DEPRECATED
@@ -98467,6 +97384,18 @@ abort_due_to_error:
rc = SQLITE_CORRUPT_BKPT;
}
assert( rc );
+#ifdef SQLITE_DEBUG
+ if( db->flags & SQLITE_VdbeTrace ){
+ const char *zTrace = p->zSql;
+ if( zTrace==0 ){
+ if( aOp[0].opcode==OP_Trace ){
+ zTrace = aOp[0].p4.z;
+ }
+ if( zTrace==0 ) zTrace = "???";
+ }
+ printf("ABORT-due-to-error (rc=%d): %s\n", rc, zTrace);
+ }
+#endif
if( p->zErrMsg==0 && rc!=SQLITE_IOERR_NOMEM ){
sqlcipher_sqlite3VdbeError(p, "%s", sqlcipher_sqlite3ErrStr(rc));
}
@@ -98475,8 +97404,11 @@ abort_due_to_error:
testcase( sqlcipher_sqlite3GlobalConfig.xLog!=0 );
sqlcipher_sqlite3_log(rc, "statement aborts at %d: [%s] %s",
(int)(pOp - aOp), p->zSql, p->zErrMsg);
- sqlcipher_sqlite3VdbeHalt(p);
+ if( p->eVdbeState==VDBE_RUN_STATE ) sqlcipher_sqlite3VdbeHalt(p);
if( rc==SQLITE_IOERR_NOMEM ) sqlcipher_sqlite3OomFault(db);
+ if( rc==SQLITE_CORRUPT && db->autoCommit==0 ){
+ db->flags |= SQLITE_CorruptRdOnly;
+ }
rc = SQLITE_ERROR;
if( resetSchemaOnFault>0 ){
sqlcipher_sqlite3ResetOneSchema(db, resetSchemaOnFault-1);
@@ -98608,7 +97540,10 @@ static int blobSeekToRow(Incrblob *p, sqlcipher_sqlite3_int64 iRow, char **pzErr
}
if( rc==SQLITE_ROW ){
VdbeCursor *pC = v->apCsr[0];
- u32 type = pC->nHdrParsed>p->iCol ? pC->aType[p->iCol] : 0;
+ u32 type;
+ assert( pC!=0 );
+ assert( pC->eCurType==CURTYPE_BTREE );
+ type = pC->nHdrParsed>p->iCol ? pC->aType[p->iCol] : 0;
testcase( pC->nHdrParsed==p->iCol );
testcase( pC->nHdrParsed==p->iCol+1 );
if( type<12 ){
@@ -98682,10 +97617,9 @@ SQLITE_API int sqlcipher_sqlite3_blob_open(
sqlcipher_sqlite3_mutex_enter(db->mutex);
pBlob = (Incrblob *)sqlcipher_sqlite3DbMallocZero(db, sizeof(Incrblob));
- do {
- memset(&sParse, 0, sizeof(Parse));
+ while(1){
+ sqlcipher_sqlite3ParseObjectInit(&sParse,db);
if( !pBlob ) goto blob_open_out;
- sParse.db = db;
sqlcipher_sqlite3DbFree(db, zErr);
zErr = 0;
@@ -98700,7 +97634,7 @@ SQLITE_API int sqlcipher_sqlite3_blob_open(
sqlcipher_sqlite3ErrorMsg(&sParse, "cannot open table without rowid: %s", zTable);
}
#ifndef SQLITE_OMIT_VIEW
- if( pTab && pTab->pSelect ){
+ if( pTab && IsView(pTab) ){
pTab = 0;
sqlcipher_sqlite3ErrorMsg(&sParse, "cannot open view: %s", zTable);
}
@@ -98720,7 +97654,7 @@ SQLITE_API int sqlcipher_sqlite3_blob_open(
/* Now search pTab for the exact column. */
for(iCol=0; iCol<pTab->nCol; iCol++) {
- if( sqlcipher_sqlite3StrICmp(pTab->aCol[iCol].zName, zColumn)==0 ){
+ if( sqlcipher_sqlite3StrICmp(pTab->aCol[iCol].zCnName, zColumn)==0 ){
break;
}
}
@@ -98745,7 +97679,8 @@ SQLITE_API int sqlcipher_sqlite3_blob_open(
** key columns must be indexed. The check below will pick up this
** case. */
FKey *pFKey;
- for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){
+ assert( IsOrdinaryTable(pTab) );
+ for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){
int j;
for(j=0; j<pFKey->nCol; j++){
if( pFKey->aCol[j].iFrom==iCol ){
@@ -98861,7 +97796,9 @@ SQLITE_API int sqlcipher_sqlite3_blob_open(
goto blob_open_out;
}
rc = blobSeekToRow(pBlob, iRow, &zErr);
- } while( (++nAttempt)<SQLITE_MAX_SCHEMA_RETRY && rc==SQLITE_SCHEMA );
+ if( (++nAttempt)>=SQLITE_MAX_SCHEMA_RETRY || rc!=SQLITE_SCHEMA ) break;
+ sqlcipher_sqlite3ParseObjectReset(&sParse);
+ }
blob_open_out:
if( rc==SQLITE_OK && db->mallocFailed==0 ){
@@ -98872,7 +97809,7 @@ blob_open_out:
}
sqlcipher_sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : 0), zErr);
sqlcipher_sqlite3DbFree(db, zErr);
- sqlcipher_sqlite3ParserReset(&sParse);
+ sqlcipher_sqlite3ParseObjectReset(&sParse);
rc = sqlcipher_sqlite3ApiExit(db, rc);
sqlcipher_sqlite3_mutex_leave(db->mutex);
return rc;
@@ -98952,8 +97889,10 @@ static int blobReadWrite(
*/
sqlcipher_sqlite3_int64 iKey;
iKey = sqlcipher_sqlite3BtreeIntegerKey(p->pCsr);
+ assert( v->apCsr[0]!=0 );
+ assert( v->apCsr[0]->eCurType==CURTYPE_BTREE );
sqlcipher_sqlite3VdbePreUpdateHook(
- v, v->apCsr[0], SQLITE_DELETE, p->zDb, p->pTab, iKey, -1
+ v, v->apCsr[0], SQLITE_DELETE, p->zDb, p->pTab, iKey, -1, p->iCol
);
}
#endif
@@ -99024,6 +97963,7 @@ SQLITE_API int sqlcipher_sqlite3_blob_reopen(sqlcipher_sqlite3_blob *pBlob, sqlc
rc = SQLITE_ABORT;
}else{
char *zErr;
+ ((Vdbe*)p->pStmt)->rc = SQLITE_OK;
rc = blobSeekToRow(p, iRow, &zErr);
if( rc!=SQLITE_OK ){
sqlcipher_sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : 0), zErr);
@@ -100004,7 +98944,8 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VdbeSorterInit(
}
#endif
- assert( pCsr->pKeyInfo && pCsr->pBtx==0 );
+ assert( pCsr->pKeyInfo );
+ assert( !pCsr->isEphemeral );
assert( pCsr->eCurType==CURTYPE_SORTER );
szKeyInfo = sizeof(KeyInfo) + (pCsr->pKeyInfo->nKeyField-1)*sizeof(CollSeq*);
sz = sizeof(VdbeSorter) + nWorker * sizeof(SortSubtask);
@@ -100117,8 +99058,9 @@ static void vdbeSorterWorkDebug(SortSubtask *pTask, const char *zEvent){
fprintf(stderr, "%lld:%d %s\n", t, iTask, zEvent);
}
static void vdbeSorterRewindDebug(const char *zEvent){
- i64 t;
- sqlcipher_sqlite3OsCurrentTimeInt64(sqlcipher_sqlite3_vfs_find(0), &t);
+ i64 t = 0;
+ sqlcipher_sqlite3_vfs *pVfs = sqlcipher_sqlite3_vfs_find(0);
+ if( ALWAYS(pVfs) ) sqlcipher_sqlite3OsCurrentTimeInt64(pVfs, &t);
fprintf(stderr, "%lld:X %s\n", t, zEvent);
}
static void vdbeSorterPopulateDebug(
@@ -100332,7 +99274,7 @@ static void vdbeSorterExtendFile(sqlcipher_sqlite3 *db, sqlcipher_sqlite3_file *
sqlcipher_sqlite3OsFileControlHint(pFd, SQLITE_FCNTL_CHUNK_SIZE, &chunksize);
sqlcipher_sqlite3OsFileControlHint(pFd, SQLITE_FCNTL_SIZE_HINT, &nByte);
sqlcipher_sqlite3OsFetch(pFd, 0, (int)nByte, &p);
- sqlcipher_sqlite3OsUnfetch(pFd, 0, p);
+ if( p ) sqlcipher_sqlite3OsUnfetch(pFd, 0, p);
}
}
#else
@@ -101050,6 +99992,7 @@ static int vdbeIncrMergerNew(
vdbeMergeEngineFree(pMerger);
rc = SQLITE_NOMEM_BKPT;
}
+ assert( *ppOut!=0 || rc!=SQLITE_OK );
return rc;
}
@@ -102307,7 +101250,6 @@ struct MemJournal {
int nChunkSize; /* In-memory chunk-size */
int nSpill; /* Bytes of data before flushing */
- int nSize; /* Bytes of data currently in memory */
FileChunk *pFirst; /* Head of in-memory chunk-list */
FilePoint endpoint; /* Pointer to the end of the file */
FilePoint readpoint; /* Pointer to the end of the last xRead() */
@@ -102368,14 +101310,13 @@ static int memjrnlRead(
/*
** Free the list of FileChunk structures headed at MemJournal.pFirst.
*/
-static void memjrnlFreeChunks(MemJournal *p){
+static void memjrnlFreeChunks(FileChunk *pFirst){
FileChunk *pIter;
FileChunk *pNext;
- for(pIter=p->pFirst; pIter; pIter=pNext){
+ for(pIter=pFirst; pIter; pIter=pNext){
pNext = pIter->pNext;
sqlcipher_sqlite3_free(pIter);
}
- p->pFirst = 0;
}
/*
@@ -102402,7 +101343,7 @@ static int memjrnlCreateFile(MemJournal *p){
}
if( rc==SQLITE_OK ){
/* No error has occurred. Free the in-memory buffers. */
- memjrnlFreeChunks(&copy);
+ memjrnlFreeChunks(copy.pFirst);
}
}
if( rc!=SQLITE_OK ){
@@ -102417,6 +101358,9 @@ static int memjrnlCreateFile(MemJournal *p){
}
+/* Forward reference */
+static int memjrnlTruncate(sqlcipher_sqlite3_file *pJfd, sqlite_int64 size);
+
/*
** Write data to the file.
*/
@@ -102447,22 +101391,20 @@ static int memjrnlWrite(
** the in-memory journal is being used by a connection using the
** atomic-write optimization. In this case the first 28 bytes of the
** journal file may be written as part of committing the transaction. */
- assert( iOfst==p->endpoint.iOffset || iOfst==0 );
-#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \
- || defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
+ assert( iOfst<=p->endpoint.iOffset );
+ if( iOfst>0 && iOfst!=p->endpoint.iOffset ){
+ memjrnlTruncate(pJfd, iOfst);
+ }
if( iOfst==0 && p->pFirst ){
assert( p->nChunkSize>iAmt );
memcpy((u8*)p->pFirst->zChunk, zBuf, iAmt);
- }else
-#else
- assert( iOfst>0 || p->pFirst==0 );
-#endif
- {
+ }else{
while( nWrite>0 ){
FileChunk *pChunk = p->endpoint.pChunk;
int iChunkOffset = (int)(p->endpoint.iOffset%p->nChunkSize);
int iSpace = MIN(nWrite, p->nChunkSize - iChunkOffset);
+ assert( pChunk!=0 || iChunkOffset==0 );
if( iChunkOffset==0 ){
/* New chunk is required to extend the file. */
FileChunk *pNew = sqlcipher_sqlite3_malloc(fileChunkSize(p->nChunkSize));
@@ -102477,15 +101419,15 @@ static int memjrnlWrite(
assert( !p->pFirst );
p->pFirst = pNew;
}
- p->endpoint.pChunk = pNew;
+ pChunk = p->endpoint.pChunk = pNew;
}
- memcpy((u8*)p->endpoint.pChunk->zChunk + iChunkOffset, zWrite, iSpace);
+ assert( pChunk!=0 );
+ memcpy((u8*)pChunk->zChunk + iChunkOffset, zWrite, iSpace);
zWrite += iSpace;
nWrite -= iSpace;
p->endpoint.iOffset += iSpace;
}
- p->nSize = iAmt + iOfst;
}
}
@@ -102493,19 +101435,29 @@ static int memjrnlWrite(
}
/*
-** Truncate the file.
-**
-** If the journal file is already on disk, truncate it there. Or, if it
-** is still in main memory but is being truncated to zero bytes in size,
-** ignore
+** Truncate the in-memory file.
*/
static int memjrnlTruncate(sqlcipher_sqlite3_file *pJfd, sqlite_int64 size){
MemJournal *p = (MemJournal *)pJfd;
- if( ALWAYS(size==0) ){
- memjrnlFreeChunks(p);
- p->nSize = 0;
- p->endpoint.pChunk = 0;
- p->endpoint.iOffset = 0;
+ assert( p->endpoint.pChunk==0 || p->endpoint.pChunk->pNext==0 );
+ if( size<p->endpoint.iOffset ){
+ FileChunk *pIter = 0;
+ if( size==0 ){
+ memjrnlFreeChunks(p->pFirst);
+ p->pFirst = 0;
+ }else{
+ i64 iOff = p->nChunkSize;
+ for(pIter=p->pFirst; ALWAYS(pIter) && iOff<size; pIter=pIter->pNext){
+ iOff += p->nChunkSize;
+ }
+ if( ALWAYS(pIter) ){
+ memjrnlFreeChunks(pIter->pNext);
+ pIter->pNext = 0;
+ }
+ }
+
+ p->endpoint.pChunk = pIter;
+ p->endpoint.iOffset = size;
p->readpoint.pChunk = 0;
p->readpoint.iOffset = 0;
}
@@ -102517,7 +101469,7 @@ static int memjrnlTruncate(sqlcipher_sqlite3_file *pJfd, sqlite_int64 size){
*/
static int memjrnlClose(sqlcipher_sqlite3_file *pJfd){
MemJournal *p = (MemJournal *)pJfd;
- memjrnlFreeChunks(p);
+ memjrnlFreeChunks(p->pFirst);
return SQLITE_OK;
}
@@ -102666,6 +101618,4838 @@ SQLITE_PRIVATE int sqlcipher_sqlite3JournalSize(sqlcipher_sqlite3_vfs *pVfs){
}
/************** End of memjournal.c ******************************************/
+/************** Begin file crypto.c ******************************************/
+/*
+** SQLCipher
+** http://sqlcipher.net
+**
+** Copyright (c) 2008 - 2013, ZETETIC LLC
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** * Neither the name of the ZETETIC LLC nor the
+** names of its contributors may be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY ZETETIC LLC ''AS IS'' AND ANY
+** EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+** DISCLAIMED. IN NO EVENT SHALL ZETETIC LLC BE LIABLE FOR ANY
+** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**
+*/
+/* BEGIN SQLCIPHER */
+#ifdef SQLITE_HAS_CODEC
+
+/* #include <assert.h> */
+/************** Include sqlcipher.h in the middle of crypto.c ****************/
+/************** Begin file sqlcipher.h ***************************************/
+/*
+** SQLCipher
+** sqlcipher.h developed by Stephen Lombardo (Zetetic LLC)
+** sjlombardo at zetetic dot net
+** http://zetetic.net
+**
+** Copyright (c) 2008, ZETETIC LLC
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** * Neither the name of the ZETETIC LLC nor the
+** names of its contributors may be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY ZETETIC LLC ''AS IS'' AND ANY
+** EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+** DISCLAIMED. IN NO EVENT SHALL ZETETIC LLC BE LIABLE FOR ANY
+** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**
+*/
+/* BEGIN SQLCIPHER */
+#ifdef SQLITE_HAS_CODEC
+#ifndef SQLCIPHER_H
+#define SQLCIPHER_H
+
+/* #include "sqlcipher_sqlite3.h" */
+
+#define SQLCIPHER_HMAC_SHA1 0
+#define SQLCIPHER_HMAC_SHA1_LABEL "HMAC_SHA1"
+#define SQLCIPHER_HMAC_SHA256 1
+#define SQLCIPHER_HMAC_SHA256_LABEL "HMAC_SHA256"
+#define SQLCIPHER_HMAC_SHA512 2
+#define SQLCIPHER_HMAC_SHA512_LABEL "HMAC_SHA512"
+
+
+#define SQLCIPHER_PBKDF2_HMAC_SHA1 0
+#define SQLCIPHER_PBKDF2_HMAC_SHA1_LABEL "PBKDF2_HMAC_SHA1"
+#define SQLCIPHER_PBKDF2_HMAC_SHA256 1
+#define SQLCIPHER_PBKDF2_HMAC_SHA256_LABEL "PBKDF2_HMAC_SHA256"
+#define SQLCIPHER_PBKDF2_HMAC_SHA512 2
+#define SQLCIPHER_PBKDF2_HMAC_SHA512_LABEL "PBKDF2_HMAC_SHA512"
+
+
+typedef struct {
+ int (*activate)(void *ctx);
+ int (*deactivate)(void *ctx);
+ const char* (*get_provider_name)(void *ctx);
+ int (*add_random)(void *ctx, void *buffer, int length);
+ int (*random)(void *ctx, void *buffer, int length);
+ int (*hmac)(void *ctx, int algorithm, unsigned char *hmac_key, int key_sz, unsigned char *in, int in_sz, unsigned char *in2, int in2_sz, unsigned char *out);
+ int (*kdf)(void *ctx, int algorithm, const unsigned char *pass, int pass_sz, unsigned char* salt, int salt_sz, int workfactor, int key_sz, unsigned char *key);
+ int (*cipher)(void *ctx, int mode, unsigned char *key, int key_sz, unsigned char *iv, unsigned char *in, int in_sz, unsigned char *out);
+ const char* (*get_cipher)(void *ctx);
+ int (*get_key_sz)(void *ctx);
+ int (*get_iv_sz)(void *ctx);
+ int (*get_block_sz)(void *ctx);
+ int (*get_hmac_sz)(void *ctx, int algorithm);
+ int (*ctx_init)(void **ctx);
+ int (*ctx_free)(void **ctx);
+ int (*fips_status)(void *ctx);
+ const char* (*get_provider_version)(void *ctx);
+} sqlcipher_provider;
+
+/* utility functions */
+void* sqlcipher_malloc(sqlite_uint64);
+void sqlcipher_mlock(void *, sqlite_uint64);
+void sqlcipher_munlock(void *, sqlite_uint64);
+void* sqlcipher_memset(void *, unsigned char, sqlite_uint64);
+int sqlcipher_ismemset(const void *, unsigned char, sqlite_uint64);
+int sqlcipher_memcmp(const void *, const void *, int);
+void sqlcipher_free(void *, sqlite_uint64);
+char* sqlcipher_version();
+
+/* provider interfaces */
+int sqlcipher_register_provider(sqlcipher_provider *);
+sqlcipher_provider* sqlcipher_get_provider(void);
+
+#define SQLCIPHER_MUTEX_PROVIDER 0
+#define SQLCIPHER_MUTEX_PROVIDER_ACTIVATE 1
+#define SQLCIPHER_MUTEX_PROVIDER_RAND 2
+#define SQLCIPHER_MUTEX_RESERVED1 3
+#define SQLCIPHER_MUTEX_RESERVED2 4
+#define SQLCIPHER_MUTEX_RESERVED3 5
+#define SQLCIPHER_MUTEX_COUNT 6
+
+sqlcipher_sqlite3_mutex* sqlcipher_mutex(int);
+
+#endif
+#endif
+/* END SQLCIPHER */
+
+
+/************** End of sqlcipher.h *******************************************/
+/************** Continuing where we left off in crypto.c *********************/
+/************** Include crypto.h in the middle of crypto.c *******************/
+/************** Begin file crypto.h ******************************************/
+/*
+** SQLCipher
+** crypto.h developed by Stephen Lombardo (Zetetic LLC)
+** sjlombardo at zetetic dot net
+** http://zetetic.net
+**
+** Copyright (c) 2008, ZETETIC LLC
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** * Neither the name of the ZETETIC LLC nor the
+** names of its contributors may be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY ZETETIC LLC ''AS IS'' AND ANY
+** EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+** DISCLAIMED. IN NO EVENT SHALL ZETETIC LLC BE LIABLE FOR ANY
+** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**
+*/
+/* BEGIN SQLCIPHER */
+#ifdef SQLITE_HAS_CODEC
+#ifndef CRYPTO_H
+#define CRYPTO_H
+
+/* #include "sqliteInt.h" */
+/* #include "btreeInt.h" */
+/* #include "pager.h" */
+/* #include "vdbeInt.h" */
+
+#ifdef __ANDROID__
+#include <android/log.h>
+#endif
+
+/* #include <time.h> */
+
+#if defined(_WIN32) || defined(SQLITE_OS_WINRT)
+/* #include <windows.h> ** amalgamator: dontcache ** */
+#else
+/* #include <sys/time.h> ** amalgamator: dontcache ** */
+#endif
+
+#ifndef OMIT_MEMLOCK
+#if defined(__unix__) || defined(__APPLE__) || defined(_AIX)
+/* #include <errno.h> ** amalgamator: dontcache ** */
+/* #include <unistd.h> ** amalgamator: dontcache ** */
+#include <sys/resource.h> /* amalgamator: dontcache */
+/* #include <sys/mman.h> ** amalgamator: dontcache ** */
+#endif
+#endif
+
+/* #include "sqlcipher.h" */
+
+/* extensions defined in pager.c */
+void *sqlcipherPagerGetCodec(Pager*);
+void sqlcipherPagerSetCodec(Pager*, void *(*)(void*,void*,Pgno,int), void (*)(void*,int,int), void (*)(void*), void *);
+SQLITE_API int sqlcipher_sqlite3pager_is_sj_pgno(Pager*, Pgno);
+SQLITE_API void sqlcipher_sqlite3pager_error(Pager*, int);
+SQLITE_API void sqlcipher_sqlite3pager_reset(Pager *pPager);
+/* end extensions defined in pager.c */
+
+#if !defined (SQLCIPHER_CRYPTO_CC) \
+ && !defined (SQLCIPHER_CRYPTO_LIBTOMCRYPT) \
+ && !defined (SQLCIPHER_CRYPTO_NSS) \
+ && !defined (SQLCIPHER_CRYPTO_OPENSSL)
+#define SQLCIPHER_CRYPTO_OPENSSL
+#endif
+
+#define FILE_HEADER_SZ 16
+
+#define CIPHER_XSTR(s) CIPHER_STR(s)
+#define CIPHER_STR(s) #s
+
+#ifndef CIPHER_VERSION_NUMBER
+#define CIPHER_VERSION_NUMBER 4.5.3
+#endif
+
+#ifndef CIPHER_VERSION_BUILD
+#define CIPHER_VERSION_BUILD community
+#endif
+
+#define CIPHER_DECRYPT 0
+#define CIPHER_ENCRYPT 1
+
+#define CIPHER_READ_CTX 0
+#define CIPHER_WRITE_CTX 1
+#define CIPHER_READWRITE_CTX 2
+
+#ifndef PBKDF2_ITER
+#define PBKDF2_ITER 256000
+#endif
+
+/* possible flags for cipher_ctx->flags */
+#define CIPHER_FLAG_HMAC 0x01
+#define CIPHER_FLAG_LE_PGNO 0x02
+#define CIPHER_FLAG_BE_PGNO 0x04
+
+#ifndef DEFAULT_CIPHER_FLAGS
+#define DEFAULT_CIPHER_FLAGS CIPHER_FLAG_HMAC | CIPHER_FLAG_LE_PGNO
+#endif
+
+
+/* by default, sqlcipher will use a reduced number of iterations to generate
+ the HMAC key / or transform a raw cipher key
+ */
+#ifndef FAST_PBKDF2_ITER
+#define FAST_PBKDF2_ITER 2
+#endif
+
+/* this if a fixed random array that will be xor'd with the database salt to ensure that the
+ salt passed to the HMAC key derivation function is not the same as that used to derive
+ the encryption key. This can be overridden at compile time but it will make the resulting
+ binary incompatible with the default builds when using HMAC. A future version of SQLcipher
+ will likely allow this to be defined at runtime via pragma */
+#ifndef HMAC_SALT_MASK
+#define HMAC_SALT_MASK 0x3a
+#endif
+
+#ifndef CIPHER_MAX_IV_SZ
+#define CIPHER_MAX_IV_SZ 16
+#endif
+
+#ifndef CIPHER_MAX_KEY_SZ
+#define CIPHER_MAX_KEY_SZ 64
+#endif
+
+
+/*
+** Simple shared routines for converting hex char strings to binary data
+ */
+static int cipher_hex2int(char c) {
+ return (c>='0' && c<='9') ? (c)-'0' :
+ (c>='A' && c<='F') ? (c)-'A'+10 :
+ (c>='a' && c<='f') ? (c)-'a'+10 : 0;
+}
+
+static void cipher_hex2bin(const unsigned char *hex, int sz, unsigned char *out){
+ int i;
+ for(i = 0; i < sz; i += 2){
+ out[i/2] = (cipher_hex2int(hex[i])<<4) | cipher_hex2int(hex[i+1]);
+ }
+}
+
+static void cipher_bin2hex(const unsigned char* in, int sz, char *out) {
+ int i;
+ for(i=0; i < sz; i++) {
+ sqlcipher_sqlite3_snprintf(3, out + (i*2), "%02x ", in[i]);
+ }
+}
+
+static int cipher_isHex(const unsigned char *hex, int sz){
+ int i;
+ for(i = 0; i < sz; i++) {
+ unsigned char c = hex[i];
+ if ((c < '0' || c > '9') &&
+ (c < 'A' || c > 'F') &&
+ (c < 'a' || c > 'f')) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/* possible flags for simulating specific test conditions */
+#ifdef SQLCIPHER_TEST
+#define TEST_FAIL_ENCRYPT 0x01
+#define TEST_FAIL_DECRYPT 0x02
+#define TEST_FAIL_MIGRATE 0x04
+unsigned int sqlcipher_get_test_flags(void);
+void sqlcipher_set_test_flags(unsigned int);
+int sqlcipher_get_test_rand(void);
+void sqlcipher_set_test_rand(int);
+int sqlcipher_get_test_fail(void);
+#endif
+
+/* extensions defined in crypto_impl.c */
+/* the default implementation of SQLCipher uses a cipher_ctx
+ to keep track of read / write state separately. The following
+ struct and associated functions are defined here */
+typedef struct {
+ int derive_key;
+ int pass_sz;
+ unsigned char *key;
+ unsigned char *hmac_key;
+ unsigned char *pass;
+ char *keyspec;
+} cipher_ctx;
+
+
+typedef struct {
+ int store_pass;
+ int kdf_iter;
+ int fast_kdf_iter;
+ int kdf_salt_sz;
+ int key_sz;
+ int iv_sz;
+ int block_sz;
+ int page_sz;
+ int keyspec_sz;
+ int reserve_sz;
+ int hmac_sz;
+ int plaintext_header_sz;
+ int hmac_algorithm;
+ int kdf_algorithm;
+ unsigned int skip_read_hmac;
+ unsigned int need_kdf_salt;
+ unsigned int flags;
+ unsigned char *kdf_salt;
+ unsigned char *hmac_kdf_salt;
+ unsigned char *buffer;
+ Btree *pBt;
+ cipher_ctx *read_ctx;
+ cipher_ctx *write_ctx;
+ sqlcipher_provider *provider;
+ void *provider_ctx;
+} codec_ctx ;
+
+/* crypto.c functions */
+int sqlcipher_codec_pragma(sqlcipher_sqlite3*, int, Parse*, const char *, const char*);
+int sqlcipherCodecAttach(sqlcipher_sqlite3*, int, const void *, int);
+void sqlcipherCodecGetKey(sqlcipher_sqlite3*, int, void**, int*);
+void sqlcipher_exportFunc(sqlcipher_sqlite3_context *, int, sqlcipher_sqlite3_value **);
+
+/* crypto_impl.c functions */
+
+void sqlcipher_init_memmethods(void);
+
+/* activation and initialization */
+void sqlcipher_activate(void);
+void sqlcipher_deactivate(void);
+
+int sqlcipher_codec_ctx_init(codec_ctx **, Db *, Pager *, const void *, int);
+void sqlcipher_codec_ctx_free(codec_ctx **);
+int sqlcipher_codec_key_derive(codec_ctx *);
+int sqlcipher_codec_key_copy(codec_ctx *, int);
+
+/* page cipher implementation */
+int sqlcipher_page_cipher(codec_ctx *, int, Pgno, int, int, unsigned char *, unsigned char *);
+
+/* context setters & getters */
+void sqlcipher_codec_ctx_set_error(codec_ctx *, int);
+
+void sqlcipher_codec_get_pass(codec_ctx *, void **, int *);
+int sqlcipher_codec_ctx_set_pass(codec_ctx *, const void *, int, int);
+void sqlcipher_codec_get_keyspec(codec_ctx *, void **zKey, int *nKey);
+
+int sqlcipher_codec_ctx_set_pagesize(codec_ctx *, int);
+int sqlcipher_codec_ctx_get_pagesize(codec_ctx *);
+int sqlcipher_codec_ctx_get_reservesize(codec_ctx *);
+
+void sqlcipher_set_default_pagesize(int page_size);
+int sqlcipher_get_default_pagesize(void);
+
+void sqlcipher_set_default_kdf_iter(int iter);
+int sqlcipher_get_default_kdf_iter(void);
+int sqlcipher_codec_ctx_set_kdf_iter(codec_ctx *, int);
+int sqlcipher_codec_ctx_get_kdf_iter(codec_ctx *ctx);
+
+int sqlcipher_codec_ctx_set_kdf_salt(codec_ctx *ctx, unsigned char *salt, int sz);
+int sqlcipher_codec_ctx_get_kdf_salt(codec_ctx *ctx, void **salt);
+
+int sqlcipher_codec_ctx_set_fast_kdf_iter(codec_ctx *, int);
+int sqlcipher_codec_ctx_get_fast_kdf_iter(codec_ctx *);
+
+const char* sqlcipher_codec_ctx_get_cipher(codec_ctx *ctx);
+
+void* sqlcipher_codec_ctx_get_data(codec_ctx *);
+
+void sqlcipher_set_default_use_hmac(int use);
+int sqlcipher_get_default_use_hmac(void);
+
+void sqlcipher_set_hmac_salt_mask(unsigned char mask);
+unsigned char sqlcipher_get_hmac_salt_mask(void);
+
+int sqlcipher_codec_ctx_set_use_hmac(codec_ctx *ctx, int use);
+int sqlcipher_codec_ctx_get_use_hmac(codec_ctx *ctx);
+
+int sqlcipher_codec_ctx_set_flag(codec_ctx *ctx, unsigned int flag);
+int sqlcipher_codec_ctx_unset_flag(codec_ctx *ctx, unsigned int flag);
+int sqlcipher_codec_ctx_get_flag(codec_ctx *ctx, unsigned int flag);
+
+const char* sqlcipher_codec_get_cipher_provider(codec_ctx *ctx);
+int sqlcipher_codec_ctx_migrate(codec_ctx *ctx);
+int sqlcipher_codec_add_random(codec_ctx *ctx, const char *data, int random_sz);
+int sqlcipher_cipher_profile(sqlcipher_sqlite3 *db, const char *destination);
+int sqlcipher_codec_get_store_pass(codec_ctx *ctx);
+void sqlcipher_codec_get_pass(codec_ctx *ctx, void **zKey, int *nKey);
+void sqlcipher_codec_set_store_pass(codec_ctx *ctx, int value);
+int sqlcipher_codec_fips_status(codec_ctx *ctx);
+const char* sqlcipher_codec_get_provider_version(codec_ctx *ctx);
+
+int sqlcipher_set_default_plaintext_header_size(int size);
+int sqlcipher_get_default_plaintext_header_size(void);
+int sqlcipher_codec_ctx_set_plaintext_header_size(codec_ctx *ctx, int size);
+int sqlcipher_codec_ctx_get_plaintext_header_size(codec_ctx *ctx);
+
+int sqlcipher_set_default_hmac_algorithm(int algorithm);
+int sqlcipher_get_default_hmac_algorithm(void);
+int sqlcipher_codec_ctx_set_hmac_algorithm(codec_ctx *ctx, int algorithm);
+int sqlcipher_codec_ctx_get_hmac_algorithm(codec_ctx *ctx);
+
+int sqlcipher_set_default_kdf_algorithm(int algorithm);
+int sqlcipher_get_default_kdf_algorithm(void);
+int sqlcipher_codec_ctx_set_kdf_algorithm(codec_ctx *ctx, int algorithm);
+int sqlcipher_codec_ctx_get_kdf_algorithm(codec_ctx *ctx);
+
+void sqlcipher_set_mem_security(int);
+int sqlcipher_get_mem_security(void);
+
+int sqlcipher_find_db_index(sqlcipher_sqlite3 *db, const char *zDb);
+
+int sqlcipher_codec_ctx_integrity_check(codec_ctx *, Parse *, char *);
+
+int sqlcipher_set_log(const char *destination);
+void sqlcipher_set_log_level(unsigned int level);
+void sqlcipher_log(unsigned int tag, const char *message, ...);
+
+#define SQLCIPHER_LOG_NONE 0x00
+#define SQLCIPHER_LOG_ERROR 0x01
+#define SQLCIPHER_LOG_WARN 0x02
+#define SQLCIPHER_LOG_INFO 0x04
+#define SQLCIPHER_LOG_DEBUG 0x08
+#define SQLCIPHER_LOG_TRACE 0x10
+#define SQLCIPHER_LOG_ALL 0xffffffff
+
+void sqlcipher_vdbe_return_string(Parse*, const char*, const char*, int);
+
+#ifdef CODEC_DEBUG_PAGEDATA
+#define CODEC_HEXDUMP(DESC,BUFFER,LEN) \
+ { \
+ int __pctr; \
+ printf(DESC); \
+ for(__pctr=0; __pctr < LEN; __pctr++) { \
+ if(__pctr % 16 == 0) printf("\n%05x: ",__pctr); \
+ printf("%02x ",((unsigned char*) BUFFER)[__pctr]); \
+ } \
+ printf("\n"); \
+ fflush(stdout); \
+ }
+#else
+#define CODEC_HEXDUMP(DESC,BUFFER,LEN)
+#endif
+
+#endif
+#endif
+/* END SQLCIPHER */
+
+/************** End of crypto.h **********************************************/
+/************** Continuing where we left off in crypto.c *********************/
+
+#ifdef SQLCIPHER_EXT
+#include "sqlcipher_ext.h"
+#endif
+
+void sqlcipher_vdbe_return_string(Parse *pParse, const char *zLabel, const char *value, int value_type){
+ Vdbe *v = sqlcipher_sqlite3GetVdbe(pParse);
+ sqlcipher_sqlite3VdbeSetNumCols(v, 1);
+ sqlcipher_sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLabel, SQLITE_STATIC);
+ sqlcipher_sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, value, value_type);
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
+}
+
+static int codec_set_btree_to_codec_pagesize(sqlcipher_sqlite3 *db, Db *pDb, codec_ctx *ctx) {
+ int rc, page_sz, reserve_sz;
+
+ page_sz = sqlcipher_codec_ctx_get_pagesize(ctx);
+ reserve_sz = sqlcipher_codec_ctx_get_reservesize(ctx);
+
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "codec_set_btree_to_codec_pagesize: sqlcipher_sqlite3BtreeSetPageSize() size=%d reserve=%d", page_sz, reserve_sz);
+
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "codec_set_btree_to_codec_pagesize: entering database mutex %p", db->mutex);
+ sqlcipher_sqlite3_mutex_enter(db->mutex);
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "codec_set_btree_to_codec_pagesize: entered database mutex %p", db->mutex);
+ db->nextPagesize = page_sz;
+
+ /* before forcing the page size we need to unset the BTS_PAGESIZE_FIXED flag, else
+ sqliteBtreeSetPageSize will block the change */
+ pDb->pBt->pBt->btsFlags &= ~BTS_PAGESIZE_FIXED;
+ rc = sqlcipher_sqlite3BtreeSetPageSize(pDb->pBt, page_sz, reserve_sz, 0);
+
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "codec_set_btree_to_codec_pagesize: sqlcipher_sqlite3BtreeSetPageSize returned %d", rc);
+
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "codec_set_btree_to_codec_pagesize: leaving database mutex %p", db->mutex);
+ sqlcipher_sqlite3_mutex_leave(db->mutex);
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "codec_set_btree_to_codec_pagesize: left database mutex %p", db->mutex);
+
+ return rc;
+}
+
+static int codec_set_pass_key(sqlcipher_sqlite3* db, int nDb, const void *zKey, int nKey, int for_ctx) {
+ struct Db *pDb = &db->aDb[nDb];
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "codec_set_pass_key: db=%p nDb=%d for_ctx=%d", db, nDb, for_ctx);
+ if(pDb->pBt) {
+ codec_ctx *ctx = (codec_ctx*) sqlcipherPagerGetCodec(pDb->pBt->pBt->pPager);
+
+ if(ctx) {
+ return sqlcipher_codec_ctx_set_pass(ctx, zKey, nKey, for_ctx);
+ } else {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "codec_set_pass_key: error ocurred fetching codec from pager on db %d", nDb);
+ return SQLITE_ERROR;
+ }
+ }
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "codec_set_pass_key: no btree present on db %d", nDb);
+ return SQLITE_ERROR;
+}
+
+int sqlcipher_codec_pragma(sqlcipher_sqlite3* db, int iDb, Parse *pParse, const char *zLeft, const char *zRight) {
+ struct Db *pDb = &db->aDb[iDb];
+ codec_ctx *ctx = NULL;
+ int rc;
+
+ if(pDb->pBt) {
+ ctx = (codec_ctx*) sqlcipherPagerGetCodec(pDb->pBt->pBt->pPager);
+ }
+
+ if(sqlcipher_sqlite3_stricmp(zLeft, "key") !=0 && sqlcipher_sqlite3_stricmp(zLeft, "rekey") != 0) {
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "sqlcipher_codec_pragma: db=%p iDb=%d pParse=%p zLeft=%s zRight=%s ctx=%p", db, iDb, pParse, zLeft, zRight, ctx);
+ }
+
+#ifdef SQLCIPHER_EXT
+ if(sqlcipher_ext_pragma(db, iDb, pParse, zLeft, zRight)) {
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "sqlcipher_codec_pragma: PRAGMA handled by sqlcipher_ext_pragma");
+ } else
+#endif
+#ifdef SQLCIPHER_TEST
+ if( sqlcipher_sqlite3_stricmp(zLeft,"cipher_test_on")==0 ){
+ if( zRight ) {
+ unsigned int flags = sqlcipher_get_test_flags();
+ if(sqlcipher_sqlite3_stricmp(zRight, "fail_encrypt")==0) {
+ flags |= TEST_FAIL_ENCRYPT;
+ } else
+ if(sqlcipher_sqlite3_stricmp(zRight, "fail_decrypt")==0) {
+ flags |= TEST_FAIL_DECRYPT;
+ } else
+ if(sqlcipher_sqlite3_stricmp(zRight, "fail_migrate")==0) {
+ flags |= TEST_FAIL_MIGRATE;
+ }
+ sqlcipher_set_test_flags(flags);
+ }
+ } else
+ if( sqlcipher_sqlite3_stricmp(zLeft,"cipher_test_off")==0 ){
+ if( zRight ) {
+ unsigned int flags = sqlcipher_get_test_flags();
+ if(sqlcipher_sqlite3_stricmp(zRight, "fail_encrypt")==0) {
+ flags &= ~TEST_FAIL_ENCRYPT;
+ } else
+ if(sqlcipher_sqlite3_stricmp(zRight, "fail_decrypt")==0) {
+ flags &= ~TEST_FAIL_DECRYPT;
+ } else
+ if(sqlcipher_sqlite3_stricmp(zRight, "fail_migrate")==0) {
+ flags &= ~TEST_FAIL_MIGRATE;
+ }
+ sqlcipher_set_test_flags(flags);
+ }
+ } else
+ if( sqlcipher_sqlite3_stricmp(zLeft,"cipher_test")==0 ){
+ char *flags = sqlcipher_sqlite3_mprintf("%u", sqlcipher_get_test_flags());
+ sqlcipher_vdbe_return_string(pParse, "cipher_test", flags, P4_DYNAMIC);
+ }else
+ if( sqlcipher_sqlite3_stricmp(zLeft,"cipher_test_rand")==0 ){
+ if( zRight ) {
+ int rand = atoi(zRight);
+ sqlcipher_set_test_rand(rand);
+ } else {
+ char *rand = sqlcipher_sqlite3_mprintf("%d", sqlcipher_get_test_rand());
+ sqlcipher_vdbe_return_string(pParse, "cipher_test_rand", rand, P4_DYNAMIC);
+ }
+ } else
+#endif
+ if( sqlcipher_sqlite3_stricmp(zLeft, "cipher_fips_status")== 0 && !zRight ){
+ if(ctx) {
+ char *fips_mode_status = sqlcipher_sqlite3_mprintf("%d", sqlcipher_codec_fips_status(ctx));
+ sqlcipher_vdbe_return_string(pParse, "cipher_fips_status", fips_mode_status, P4_DYNAMIC);
+ }
+ } else
+ if( sqlcipher_sqlite3_stricmp(zLeft, "cipher_store_pass")==0 && zRight ) {
+ if(ctx) {
+ char *deprecation = "PRAGMA cipher_store_pass is deprecated, please remove from use";
+ sqlcipher_codec_set_store_pass(ctx, sqlcipher_sqlite3GetBoolean(zRight, 1));
+ sqlcipher_vdbe_return_string(pParse, "cipher_store_pass", deprecation, P4_TRANSIENT);
+ sqlcipher_sqlite3_log(SQLITE_WARNING, deprecation);
+ }
+ } else
+ if( sqlcipher_sqlite3_stricmp(zLeft, "cipher_store_pass")==0 && !zRight ) {
+ if(ctx){
+ char *store_pass_value = sqlcipher_sqlite3_mprintf("%d", sqlcipher_codec_get_store_pass(ctx));
+ sqlcipher_vdbe_return_string(pParse, "cipher_store_pass", store_pass_value, P4_DYNAMIC);
+ }
+ }
+ if( sqlcipher_sqlite3_stricmp(zLeft, "cipher_profile")== 0 && zRight ){
+ char *profile_status = sqlcipher_sqlite3_mprintf("%d", sqlcipher_cipher_profile(db, zRight));
+ sqlcipher_vdbe_return_string(pParse, "cipher_profile", profile_status, P4_DYNAMIC);
+ } else
+ if( sqlcipher_sqlite3_stricmp(zLeft, "cipher_add_random")==0 && zRight ){
+ if(ctx) {
+ char *add_random_status = sqlcipher_sqlite3_mprintf("%d", sqlcipher_codec_add_random(ctx, zRight, sqlcipher_sqlite3Strlen30(zRight)));
+ sqlcipher_vdbe_return_string(pParse, "cipher_add_random", add_random_status, P4_DYNAMIC);
+ }
+ } else
+ if( sqlcipher_sqlite3_stricmp(zLeft, "cipher_migrate")==0 && !zRight ){
+ if(ctx){
+ int status = sqlcipher_codec_ctx_migrate(ctx);
+ char *migrate_status = sqlcipher_sqlite3_mprintf("%d", status);
+ sqlcipher_vdbe_return_string(pParse, "cipher_migrate", migrate_status, P4_DYNAMIC);
+ if(status != SQLITE_OK) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_codec_pragma: error occurred during cipher_migrate: %d", status);
+ sqlcipher_codec_ctx_set_error(ctx, status);
+ }
+ }
+ } else
+ if( sqlcipher_sqlite3_stricmp(zLeft, "cipher_provider")==0 && !zRight ){
+ if(ctx) { sqlcipher_vdbe_return_string(pParse, "cipher_provider",
+ sqlcipher_codec_get_cipher_provider(ctx), P4_TRANSIENT);
+ }
+ } else
+ if( sqlcipher_sqlite3_stricmp(zLeft, "cipher_provider_version")==0 && !zRight){
+ if(ctx) { sqlcipher_vdbe_return_string(pParse, "cipher_provider_version",
+ sqlcipher_codec_get_provider_version(ctx), P4_TRANSIENT);
+ }
+ } else
+ if( sqlcipher_sqlite3_stricmp(zLeft, "cipher_version")==0 && !zRight ){
+ sqlcipher_vdbe_return_string(pParse, "cipher_version", sqlcipher_version(), P4_DYNAMIC);
+ }else
+ if( sqlcipher_sqlite3_stricmp(zLeft, "cipher")==0 ){
+ if(ctx) {
+ if( zRight ) {
+ const char* message = "PRAGMA cipher is no longer supported.";
+ sqlcipher_vdbe_return_string(pParse, "cipher", message, P4_TRANSIENT);
+ sqlcipher_sqlite3_log(SQLITE_WARNING, message);
+ }else {
+ sqlcipher_vdbe_return_string(pParse, "cipher", sqlcipher_codec_ctx_get_cipher(ctx), P4_TRANSIENT);
+ }
+ }
+ }else
+ if( sqlcipher_sqlite3_stricmp(zLeft, "rekey_cipher")==0 && zRight ){
+ const char* message = "PRAGMA rekey_cipher is no longer supported.";
+ sqlcipher_vdbe_return_string(pParse, "rekey_cipher", message, P4_TRANSIENT);
+ sqlcipher_sqlite3_log(SQLITE_WARNING, message);
+ }else
+ if( sqlcipher_sqlite3_stricmp(zLeft,"cipher_default_kdf_iter")==0 ){
+ if( zRight ) {
+ sqlcipher_set_default_kdf_iter(atoi(zRight)); /* change default KDF iterations */
+ } else {
+ char *kdf_iter = sqlcipher_sqlite3_mprintf("%d", sqlcipher_get_default_kdf_iter());
+ sqlcipher_vdbe_return_string(pParse, "cipher_default_kdf_iter", kdf_iter, P4_DYNAMIC);
+ }
+ }else
+ if( sqlcipher_sqlite3_stricmp(zLeft, "kdf_iter")==0 ){
+ if(ctx) {
+ if( zRight ) {
+ sqlcipher_codec_ctx_set_kdf_iter(ctx, atoi(zRight)); /* change of RW PBKDF2 iteration */
+ } else {
+ char *kdf_iter = sqlcipher_sqlite3_mprintf("%d", sqlcipher_codec_ctx_get_kdf_iter(ctx));
+ sqlcipher_vdbe_return_string(pParse, "kdf_iter", kdf_iter, P4_DYNAMIC);
+ }
+ }
+ }else
+ if( sqlcipher_sqlite3_stricmp(zLeft, "fast_kdf_iter")==0){
+ if(ctx) {
+ if( zRight ) {
+ char *deprecation = "PRAGMA fast_kdf_iter is deprecated, please remove from use";
+ sqlcipher_codec_ctx_set_fast_kdf_iter(ctx, atoi(zRight)); /* change of RW PBKDF2 iteration */
+ sqlcipher_vdbe_return_string(pParse, "fast_kdf_iter", deprecation, P4_TRANSIENT);
+ sqlcipher_sqlite3_log(SQLITE_WARNING, deprecation);
+ } else {
+ char *fast_kdf_iter = sqlcipher_sqlite3_mprintf("%d", sqlcipher_codec_ctx_get_fast_kdf_iter(ctx));
+ sqlcipher_vdbe_return_string(pParse, "fast_kdf_iter", fast_kdf_iter, P4_DYNAMIC);
+ }
+ }
+ }else
+ if( sqlcipher_sqlite3_stricmp(zLeft, "rekey_kdf_iter")==0 && zRight ){
+ const char* message = "PRAGMA rekey_kdf_iter is no longer supported.";
+ sqlcipher_vdbe_return_string(pParse, "rekey_kdf_iter", message, P4_TRANSIENT);
+ sqlcipher_sqlite3_log(SQLITE_WARNING, message);
+ }else
+ if( sqlcipher_sqlite3_stricmp(zLeft,"cipher_page_size")==0 ){
+ if(ctx) {
+ if( zRight ) {
+ int size = atoi(zRight);
+ rc = sqlcipher_codec_ctx_set_pagesize(ctx, size);
+ if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc);
+ rc = codec_set_btree_to_codec_pagesize(db, pDb, ctx);
+ if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc);
+ } else {
+ char * page_size = sqlcipher_sqlite3_mprintf("%d", sqlcipher_codec_ctx_get_pagesize(ctx));
+ sqlcipher_vdbe_return_string(pParse, "cipher_page_size", page_size, P4_DYNAMIC);
+ }
+ }
+ }else
+ if( sqlcipher_sqlite3_stricmp(zLeft,"cipher_default_page_size")==0 ){
+ if( zRight ) {
+ sqlcipher_set_default_pagesize(atoi(zRight));
+ } else {
+ char *default_page_size = sqlcipher_sqlite3_mprintf("%d", sqlcipher_get_default_pagesize());
+ sqlcipher_vdbe_return_string(pParse, "cipher_default_page_size", default_page_size, P4_DYNAMIC);
+ }
+ }else
+ if( sqlcipher_sqlite3_stricmp(zLeft,"cipher_default_use_hmac")==0 ){
+ if( zRight ) {
+ sqlcipher_set_default_use_hmac(sqlcipher_sqlite3GetBoolean(zRight,1));
+ } else {
+ char *default_use_hmac = sqlcipher_sqlite3_mprintf("%d", sqlcipher_get_default_use_hmac());
+ sqlcipher_vdbe_return_string(pParse, "cipher_default_use_hmac", default_use_hmac, P4_DYNAMIC);
+ }
+ }else
+ if( sqlcipher_sqlite3_stricmp(zLeft,"cipher_use_hmac")==0 ){
+ if(ctx) {
+ if( zRight ) {
+ rc = sqlcipher_codec_ctx_set_use_hmac(ctx, sqlcipher_sqlite3GetBoolean(zRight,1));
+ if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc);
+ /* since the use of hmac has changed, the page size may also change */
+ rc = codec_set_btree_to_codec_pagesize(db, pDb, ctx);
+ if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc);
+ } else {
+ char *hmac_flag = sqlcipher_sqlite3_mprintf("%d", sqlcipher_codec_ctx_get_use_hmac(ctx));
+ sqlcipher_vdbe_return_string(pParse, "cipher_use_hmac", hmac_flag, P4_DYNAMIC);
+ }
+ }
+ }else
+ if( sqlcipher_sqlite3_stricmp(zLeft,"cipher_hmac_pgno")==0 ){
+ if(ctx) {
+ if(zRight) {
+ char *deprecation = "PRAGMA cipher_hmac_pgno is deprecated, please remove from use";
+ /* clear both pgno endian flags */
+ if(sqlcipher_sqlite3_stricmp(zRight, "le") == 0) {
+ sqlcipher_codec_ctx_unset_flag(ctx, CIPHER_FLAG_BE_PGNO);
+ sqlcipher_codec_ctx_set_flag(ctx, CIPHER_FLAG_LE_PGNO);
+ } else if(sqlcipher_sqlite3_stricmp(zRight, "be") == 0) {
+ sqlcipher_codec_ctx_unset_flag(ctx, CIPHER_FLAG_LE_PGNO);
+ sqlcipher_codec_ctx_set_flag(ctx, CIPHER_FLAG_BE_PGNO);
+ } else if(sqlcipher_sqlite3_stricmp(zRight, "native") == 0) {
+ sqlcipher_codec_ctx_unset_flag(ctx, CIPHER_FLAG_LE_PGNO);
+ sqlcipher_codec_ctx_unset_flag(ctx, CIPHER_FLAG_BE_PGNO);
+ }
+ sqlcipher_vdbe_return_string(pParse, "cipher_hmac_pgno", deprecation, P4_TRANSIENT);
+ sqlcipher_sqlite3_log(SQLITE_WARNING, deprecation);
+
+ } else {
+ if(sqlcipher_codec_ctx_get_flag(ctx, CIPHER_FLAG_LE_PGNO)) {
+ sqlcipher_vdbe_return_string(pParse, "cipher_hmac_pgno", "le", P4_TRANSIENT);
+ } else if(sqlcipher_codec_ctx_get_flag(ctx, CIPHER_FLAG_BE_PGNO)) {
+ sqlcipher_vdbe_return_string(pParse, "cipher_hmac_pgno", "be", P4_TRANSIENT);
+ } else {
+ sqlcipher_vdbe_return_string(pParse, "cipher_hmac_pgno", "native", P4_TRANSIENT);
+ }
+ }
+ }
+ }else
+ if( sqlcipher_sqlite3_stricmp(zLeft,"cipher_hmac_salt_mask")==0 ){
+ if(ctx) {
+ if(zRight) {
+ char *deprecation = "PRAGMA cipher_hmac_salt_mask is deprecated, please remove from use";
+ if (sqlcipher_sqlite3StrNICmp(zRight ,"x'", 2) == 0 && sqlcipher_sqlite3Strlen30(zRight) == 5) {
+ unsigned char mask = 0;
+ const unsigned char *hex = (const unsigned char *)zRight+2;
+ cipher_hex2bin(hex,2,&mask);
+ sqlcipher_set_hmac_salt_mask(mask);
+ }
+ sqlcipher_vdbe_return_string(pParse, "cipher_hmac_salt_mask", deprecation, P4_TRANSIENT);
+ sqlcipher_sqlite3_log(SQLITE_WARNING, deprecation);
+ } else {
+ char *hmac_salt_mask = sqlcipher_sqlite3_mprintf("%02x", sqlcipher_get_hmac_salt_mask());
+ sqlcipher_vdbe_return_string(pParse, "cipher_hmac_salt_mask", hmac_salt_mask, P4_DYNAMIC);
+ }
+ }
+ }else
+ if( sqlcipher_sqlite3_stricmp(zLeft,"cipher_plaintext_header_size")==0 ){
+ if(ctx) {
+ if( zRight ) {
+ int size = atoi(zRight);
+ /* deliberately ignore result code, if size is invalid it will be set to -1
+ and trip the error later in the codec */
+ sqlcipher_codec_ctx_set_plaintext_header_size(ctx, size);
+ } else {
+ char *size = sqlcipher_sqlite3_mprintf("%d", sqlcipher_codec_ctx_get_plaintext_header_size(ctx));
+ sqlcipher_vdbe_return_string(pParse, "cipher_plaintext_header_size", size, P4_DYNAMIC);
+ }
+ }
+ }else
+ if( sqlcipher_sqlite3_stricmp(zLeft,"cipher_default_plaintext_header_size")==0 ){
+ if( zRight ) {
+ sqlcipher_set_default_plaintext_header_size(atoi(zRight));
+ } else {
+ char *size = sqlcipher_sqlite3_mprintf("%d", sqlcipher_get_default_plaintext_header_size());
+ sqlcipher_vdbe_return_string(pParse, "cipher_default_plaintext_header_size", size, P4_DYNAMIC);
+ }
+ }else
+ if( sqlcipher_sqlite3_stricmp(zLeft,"cipher_salt")==0 ){
+ if(ctx) {
+ if(zRight) {
+ if (sqlcipher_sqlite3StrNICmp(zRight ,"x'", 2) == 0 && sqlcipher_sqlite3Strlen30(zRight) == (FILE_HEADER_SZ*2)+3) {
+ unsigned char *salt = (unsigned char*) sqlcipher_sqlite3_malloc(FILE_HEADER_SZ);
+ const unsigned char *hex = (const unsigned char *)zRight+2;
+ cipher_hex2bin(hex,FILE_HEADER_SZ*2,salt);
+ sqlcipher_codec_ctx_set_kdf_salt(ctx, salt, FILE_HEADER_SZ);
+ sqlcipher_sqlite3_free(salt);
+ }
+ } else {
+ void *salt;
+ char *hexsalt = (char*) sqlcipher_sqlite3_malloc((FILE_HEADER_SZ*2)+1);
+ if((rc = sqlcipher_codec_ctx_get_kdf_salt(ctx, &salt)) == SQLITE_OK) {
+ cipher_bin2hex(salt, FILE_HEADER_SZ, hexsalt);
+ sqlcipher_vdbe_return_string(pParse, "cipher_salt", hexsalt, P4_DYNAMIC);
+ } else {
+ sqlcipher_sqlite3_free(hexsalt);
+ sqlcipher_codec_ctx_set_error(ctx, rc);
+ }
+ }
+ }
+ }else
+ if( sqlcipher_sqlite3_stricmp(zLeft,"cipher_hmac_algorithm")==0 ){
+ if(ctx) {
+ if(zRight) {
+ rc = SQLITE_ERROR;
+ if(sqlcipher_sqlite3_stricmp(zRight, SQLCIPHER_HMAC_SHA1_LABEL) == 0) {
+ rc = sqlcipher_codec_ctx_set_hmac_algorithm(ctx, SQLCIPHER_HMAC_SHA1);
+ } else if(sqlcipher_sqlite3_stricmp(zRight, SQLCIPHER_HMAC_SHA256_LABEL) == 0) {
+ rc = sqlcipher_codec_ctx_set_hmac_algorithm(ctx, SQLCIPHER_HMAC_SHA256);
+ } else if(sqlcipher_sqlite3_stricmp(zRight, SQLCIPHER_HMAC_SHA512_LABEL) == 0) {
+ rc = sqlcipher_codec_ctx_set_hmac_algorithm(ctx, SQLCIPHER_HMAC_SHA512);
+ }
+ if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
+ rc = codec_set_btree_to_codec_pagesize(db, pDb, ctx);
+ if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
+ } else {
+ int algorithm = sqlcipher_codec_ctx_get_hmac_algorithm(ctx);
+ if(algorithm == SQLCIPHER_HMAC_SHA1) {
+ sqlcipher_vdbe_return_string(pParse, "cipher_hmac_algorithm", SQLCIPHER_HMAC_SHA1_LABEL, P4_TRANSIENT);
+ } else if(algorithm == SQLCIPHER_HMAC_SHA256) {
+ sqlcipher_vdbe_return_string(pParse, "cipher_hmac_algorithm", SQLCIPHER_HMAC_SHA256_LABEL, P4_TRANSIENT);
+ } else if(algorithm == SQLCIPHER_HMAC_SHA512) {
+ sqlcipher_vdbe_return_string(pParse, "cipher_hmac_algorithm", SQLCIPHER_HMAC_SHA512_LABEL, P4_TRANSIENT);
+ }
+ }
+ }
+ }else
+ if( sqlcipher_sqlite3_stricmp(zLeft,"cipher_default_hmac_algorithm")==0 ){
+ if(zRight) {
+ rc = SQLITE_ERROR;
+ if(sqlcipher_sqlite3_stricmp(zRight, SQLCIPHER_HMAC_SHA1_LABEL) == 0) {
+ rc = sqlcipher_set_default_hmac_algorithm(SQLCIPHER_HMAC_SHA1);
+ } else if(sqlcipher_sqlite3_stricmp(zRight, SQLCIPHER_HMAC_SHA256_LABEL) == 0) {
+ rc = sqlcipher_set_default_hmac_algorithm(SQLCIPHER_HMAC_SHA256);
+ } else if(sqlcipher_sqlite3_stricmp(zRight, SQLCIPHER_HMAC_SHA512_LABEL) == 0) {
+ rc = sqlcipher_set_default_hmac_algorithm(SQLCIPHER_HMAC_SHA512);
+ }
+ } else {
+ int algorithm = sqlcipher_get_default_hmac_algorithm();
+ if(algorithm == SQLCIPHER_HMAC_SHA1) {
+ sqlcipher_vdbe_return_string(pParse, "cipher_default_hmac_algorithm", SQLCIPHER_HMAC_SHA1_LABEL, P4_TRANSIENT);
+ } else if(algorithm == SQLCIPHER_HMAC_SHA256) {
+ sqlcipher_vdbe_return_string(pParse, "cipher_default_hmac_algorithm", SQLCIPHER_HMAC_SHA256_LABEL, P4_TRANSIENT);
+ } else if(algorithm == SQLCIPHER_HMAC_SHA512) {
+ sqlcipher_vdbe_return_string(pParse, "cipher_default_hmac_algorithm", SQLCIPHER_HMAC_SHA512_LABEL, P4_TRANSIENT);
+ }
+ }
+ }else
+ if( sqlcipher_sqlite3_stricmp(zLeft,"cipher_kdf_algorithm")==0 ){
+ if(ctx) {
+ if(zRight) {
+ rc = SQLITE_ERROR;
+ if(sqlcipher_sqlite3_stricmp(zRight, SQLCIPHER_PBKDF2_HMAC_SHA1_LABEL) == 0) {
+ rc = sqlcipher_codec_ctx_set_kdf_algorithm(ctx, SQLCIPHER_PBKDF2_HMAC_SHA1);
+ } else if(sqlcipher_sqlite3_stricmp(zRight, SQLCIPHER_PBKDF2_HMAC_SHA256_LABEL) == 0) {
+ rc = sqlcipher_codec_ctx_set_kdf_algorithm(ctx, SQLCIPHER_PBKDF2_HMAC_SHA256);
+ } else if(sqlcipher_sqlite3_stricmp(zRight, SQLCIPHER_PBKDF2_HMAC_SHA512_LABEL) == 0) {
+ rc = sqlcipher_codec_ctx_set_kdf_algorithm(ctx, SQLCIPHER_PBKDF2_HMAC_SHA512);
+ }
+ if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
+ } else {
+ int algorithm = sqlcipher_codec_ctx_get_kdf_algorithm(ctx);
+ if(algorithm == SQLCIPHER_PBKDF2_HMAC_SHA1) {
+ sqlcipher_vdbe_return_string(pParse, "cipher_kdf_algorithm", SQLCIPHER_PBKDF2_HMAC_SHA1_LABEL, P4_TRANSIENT);
+ } else if(algorithm == SQLCIPHER_PBKDF2_HMAC_SHA256) {
+ sqlcipher_vdbe_return_string(pParse, "cipher_kdf_algorithm", SQLCIPHER_PBKDF2_HMAC_SHA256_LABEL, P4_TRANSIENT);
+ } else if(algorithm == SQLCIPHER_PBKDF2_HMAC_SHA512) {
+ sqlcipher_vdbe_return_string(pParse, "cipher_kdf_algorithm", SQLCIPHER_PBKDF2_HMAC_SHA512_LABEL, P4_TRANSIENT);
+ }
+ }
+ }
+ }else
+ if( sqlcipher_sqlite3_stricmp(zLeft,"cipher_default_kdf_algorithm")==0 ){
+ if(zRight) {
+ rc = SQLITE_ERROR;
+ if(sqlcipher_sqlite3_stricmp(zRight, SQLCIPHER_PBKDF2_HMAC_SHA1_LABEL) == 0) {
+ rc = sqlcipher_set_default_kdf_algorithm(SQLCIPHER_PBKDF2_HMAC_SHA1);
+ } else if(sqlcipher_sqlite3_stricmp(zRight, SQLCIPHER_PBKDF2_HMAC_SHA256_LABEL) == 0) {
+ rc = sqlcipher_set_default_kdf_algorithm(SQLCIPHER_PBKDF2_HMAC_SHA256);
+ } else if(sqlcipher_sqlite3_stricmp(zRight, SQLCIPHER_PBKDF2_HMAC_SHA512_LABEL) == 0) {
+ rc = sqlcipher_set_default_kdf_algorithm(SQLCIPHER_PBKDF2_HMAC_SHA512);
+ }
+ } else {
+ int algorithm = sqlcipher_get_default_kdf_algorithm();
+ if(algorithm == SQLCIPHER_PBKDF2_HMAC_SHA1) {
+ sqlcipher_vdbe_return_string(pParse, "cipher_default_kdf_algorithm", SQLCIPHER_PBKDF2_HMAC_SHA1_LABEL, P4_TRANSIENT);
+ } else if(algorithm == SQLCIPHER_PBKDF2_HMAC_SHA256) {
+ sqlcipher_vdbe_return_string(pParse, "cipher_default_kdf_algorithm", SQLCIPHER_PBKDF2_HMAC_SHA256_LABEL, P4_TRANSIENT);
+ } else if(algorithm == SQLCIPHER_PBKDF2_HMAC_SHA512) {
+ sqlcipher_vdbe_return_string(pParse, "cipher_default_kdf_algorithm", SQLCIPHER_PBKDF2_HMAC_SHA512_LABEL, P4_TRANSIENT);
+ }
+ }
+ }else
+ if( sqlcipher_sqlite3_stricmp(zLeft,"cipher_compatibility")==0 ){
+ if(ctx) {
+ if(zRight) {
+ int version = atoi(zRight);
+
+ switch(version) {
+ case 1:
+ rc = sqlcipher_codec_ctx_set_pagesize(ctx, 1024);
+ if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
+ rc = sqlcipher_codec_ctx_set_hmac_algorithm(ctx, SQLCIPHER_HMAC_SHA1);
+ if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
+ rc = sqlcipher_codec_ctx_set_kdf_algorithm(ctx, SQLCIPHER_PBKDF2_HMAC_SHA1);
+ if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
+ rc = sqlcipher_codec_ctx_set_kdf_iter(ctx, 4000);
+ if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
+ rc = sqlcipher_codec_ctx_set_use_hmac(ctx, 0);
+ if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
+ break;
+
+ case 2:
+ rc = sqlcipher_codec_ctx_set_pagesize(ctx, 1024);
+ if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
+ rc = sqlcipher_codec_ctx_set_hmac_algorithm(ctx, SQLCIPHER_HMAC_SHA1);
+ if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
+ rc = sqlcipher_codec_ctx_set_kdf_algorithm(ctx, SQLCIPHER_PBKDF2_HMAC_SHA1);
+ if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
+ rc = sqlcipher_codec_ctx_set_kdf_iter(ctx, 4000);
+ if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
+ rc = sqlcipher_codec_ctx_set_use_hmac(ctx, 1);
+ if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
+ break;
+
+ case 3:
+ rc = sqlcipher_codec_ctx_set_pagesize(ctx, 1024);
+ if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
+ rc = sqlcipher_codec_ctx_set_hmac_algorithm(ctx, SQLCIPHER_HMAC_SHA1);
+ if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
+ rc = sqlcipher_codec_ctx_set_kdf_algorithm(ctx, SQLCIPHER_PBKDF2_HMAC_SHA1);
+ if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
+ rc = sqlcipher_codec_ctx_set_kdf_iter(ctx, 64000);
+ if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
+ rc = sqlcipher_codec_ctx_set_use_hmac(ctx, 1);
+ if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
+ break;
+
+ default:
+ rc = sqlcipher_codec_ctx_set_pagesize(ctx, 4096);
+ if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
+ rc = sqlcipher_codec_ctx_set_hmac_algorithm(ctx, SQLCIPHER_HMAC_SHA512);
+ if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
+ rc = sqlcipher_codec_ctx_set_kdf_algorithm(ctx, SQLCIPHER_PBKDF2_HMAC_SHA512);
+ if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
+ rc = sqlcipher_codec_ctx_set_kdf_iter(ctx, 256000);
+ if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
+ rc = sqlcipher_codec_ctx_set_use_hmac(ctx, 1);
+ if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
+ break;
+ }
+
+ rc = codec_set_btree_to_codec_pagesize(db, pDb, ctx);
+ if (rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
+ }
+ }
+ }else
+ if( sqlcipher_sqlite3_stricmp(zLeft,"cipher_default_compatibility")==0 ){
+ if(zRight) {
+ int version = atoi(zRight);
+ switch(version) {
+ case 1:
+ sqlcipher_set_default_pagesize(1024);
+ sqlcipher_set_default_hmac_algorithm(SQLCIPHER_HMAC_SHA1);
+ sqlcipher_set_default_kdf_algorithm(SQLCIPHER_PBKDF2_HMAC_SHA1);
+ sqlcipher_set_default_kdf_iter(4000);
+ sqlcipher_set_default_use_hmac(0);
+ break;
+
+ case 2:
+ sqlcipher_set_default_pagesize(1024);
+ sqlcipher_set_default_hmac_algorithm(SQLCIPHER_HMAC_SHA1);
+ sqlcipher_set_default_kdf_algorithm(SQLCIPHER_PBKDF2_HMAC_SHA1);
+ sqlcipher_set_default_kdf_iter(4000);
+ sqlcipher_set_default_use_hmac(1);
+ break;
+
+ case 3:
+ sqlcipher_set_default_pagesize(1024);
+ sqlcipher_set_default_hmac_algorithm(SQLCIPHER_HMAC_SHA1);
+ sqlcipher_set_default_kdf_algorithm(SQLCIPHER_PBKDF2_HMAC_SHA1);
+ sqlcipher_set_default_kdf_iter(64000);
+ sqlcipher_set_default_use_hmac(1);
+ break;
+
+ default:
+ sqlcipher_set_default_pagesize(4096);
+ sqlcipher_set_default_hmac_algorithm(SQLCIPHER_HMAC_SHA512);
+ sqlcipher_set_default_kdf_algorithm(SQLCIPHER_PBKDF2_HMAC_SHA512);
+ sqlcipher_set_default_kdf_iter(256000);
+ sqlcipher_set_default_use_hmac(1);
+ break;
+ }
+ }
+ }else
+ if( sqlcipher_sqlite3_stricmp(zLeft,"cipher_memory_security")==0 ){
+ if( zRight ) {
+ sqlcipher_set_mem_security(sqlcipher_sqlite3GetBoolean(zRight,1));
+ } else {
+ char *on = sqlcipher_sqlite3_mprintf("%d", sqlcipher_get_mem_security());
+ sqlcipher_vdbe_return_string(pParse, "cipher_memory_security", on, P4_DYNAMIC);
+ }
+ }else
+ if( sqlcipher_sqlite3_stricmp(zLeft,"cipher_settings")==0 ){
+ if(ctx) {
+ int algorithm;
+ char *pragma;
+
+ pragma = sqlcipher_sqlite3_mprintf("PRAGMA kdf_iter = %d;", sqlcipher_codec_ctx_get_kdf_iter(ctx));
+ sqlcipher_vdbe_return_string(pParse, "pragma", pragma, P4_DYNAMIC);
+
+ pragma = sqlcipher_sqlite3_mprintf("PRAGMA cipher_page_size = %d;", sqlcipher_codec_ctx_get_pagesize(ctx));
+ sqlcipher_vdbe_return_string(pParse, "pragma", pragma, P4_DYNAMIC);
+
+ pragma = sqlcipher_sqlite3_mprintf("PRAGMA cipher_use_hmac = %d;", sqlcipher_codec_ctx_get_use_hmac(ctx));
+ sqlcipher_vdbe_return_string(pParse, "pragma", pragma, P4_DYNAMIC);
+
+ pragma = sqlcipher_sqlite3_mprintf("PRAGMA cipher_plaintext_header_size = %d;", sqlcipher_codec_ctx_get_plaintext_header_size(ctx));
+ sqlcipher_vdbe_return_string(pParse, "pragma", pragma, P4_DYNAMIC);
+
+ algorithm = sqlcipher_codec_ctx_get_hmac_algorithm(ctx);
+ pragma = NULL;
+ if(algorithm == SQLCIPHER_HMAC_SHA1) {
+ pragma = sqlcipher_sqlite3_mprintf("PRAGMA cipher_hmac_algorithm = %s;", SQLCIPHER_HMAC_SHA1_LABEL);
+ } else if(algorithm == SQLCIPHER_HMAC_SHA256) {
+ pragma = sqlcipher_sqlite3_mprintf("PRAGMA cipher_hmac_algorithm = %s;", SQLCIPHER_HMAC_SHA256_LABEL);
+ } else if(algorithm == SQLCIPHER_HMAC_SHA512) {
+ pragma = sqlcipher_sqlite3_mprintf("PRAGMA cipher_hmac_algorithm = %s;", SQLCIPHER_HMAC_SHA512_LABEL);
+ }
+ sqlcipher_vdbe_return_string(pParse, "pragma", pragma, P4_DYNAMIC);
+
+ algorithm = sqlcipher_codec_ctx_get_kdf_algorithm(ctx);
+ pragma = NULL;
+ if(algorithm == SQLCIPHER_PBKDF2_HMAC_SHA1) {
+ pragma = sqlcipher_sqlite3_mprintf("PRAGMA cipher_kdf_algorithm = %s;", SQLCIPHER_PBKDF2_HMAC_SHA1_LABEL);
+ } else if(algorithm == SQLCIPHER_PBKDF2_HMAC_SHA256) {
+ pragma = sqlcipher_sqlite3_mprintf("PRAGMA cipher_kdf_algorithm = %s;", SQLCIPHER_PBKDF2_HMAC_SHA256_LABEL);
+ } else if(algorithm == SQLCIPHER_PBKDF2_HMAC_SHA512) {
+ pragma = sqlcipher_sqlite3_mprintf("PRAGMA cipher_kdf_algorithm = %s;", SQLCIPHER_PBKDF2_HMAC_SHA512_LABEL);
+ }
+ sqlcipher_vdbe_return_string(pParse, "pragma", pragma, P4_DYNAMIC);
+
+ }
+ }else
+ if( sqlcipher_sqlite3_stricmp(zLeft,"cipher_default_settings")==0 ){
+ int algorithm;
+ char *pragma;
+
+ pragma = sqlcipher_sqlite3_mprintf("PRAGMA cipher_default_kdf_iter = %d;", sqlcipher_get_default_kdf_iter());
+ sqlcipher_vdbe_return_string(pParse, "pragma", pragma, P4_DYNAMIC);
+
+ pragma = sqlcipher_sqlite3_mprintf("PRAGMA cipher_default_page_size = %d;", sqlcipher_get_default_pagesize());
+ sqlcipher_vdbe_return_string(pParse, "pragma", pragma, P4_DYNAMIC);
+
+ pragma = sqlcipher_sqlite3_mprintf("PRAGMA cipher_default_use_hmac = %d;", sqlcipher_get_default_use_hmac());
+ sqlcipher_vdbe_return_string(pParse, "pragma", pragma, P4_DYNAMIC);
+
+ pragma = sqlcipher_sqlite3_mprintf("PRAGMA cipher_default_plaintext_header_size = %d;", sqlcipher_get_default_plaintext_header_size());
+ sqlcipher_vdbe_return_string(pParse, "pragma", pragma, P4_DYNAMIC);
+
+ algorithm = sqlcipher_get_default_hmac_algorithm();
+ pragma = NULL;
+ if(algorithm == SQLCIPHER_HMAC_SHA1) {
+ pragma = sqlcipher_sqlite3_mprintf("PRAGMA cipher_default_hmac_algorithm = %s;", SQLCIPHER_HMAC_SHA1_LABEL);
+ } else if(algorithm == SQLCIPHER_HMAC_SHA256) {
+ pragma = sqlcipher_sqlite3_mprintf("PRAGMA cipher_default_hmac_algorithm = %s;", SQLCIPHER_HMAC_SHA256_LABEL);
+ } else if(algorithm == SQLCIPHER_HMAC_SHA512) {
+ pragma = sqlcipher_sqlite3_mprintf("PRAGMA cipher_default_hmac_algorithm = %s;", SQLCIPHER_HMAC_SHA512_LABEL);
+ }
+ sqlcipher_vdbe_return_string(pParse, "pragma", pragma, P4_DYNAMIC);
+
+ algorithm = sqlcipher_get_default_kdf_algorithm();
+ pragma = NULL;
+ if(algorithm == SQLCIPHER_PBKDF2_HMAC_SHA1) {
+ pragma = sqlcipher_sqlite3_mprintf("PRAGMA cipher_default_kdf_algorithm = %s;", SQLCIPHER_PBKDF2_HMAC_SHA1_LABEL);
+ } else if(algorithm == SQLCIPHER_PBKDF2_HMAC_SHA256) {
+ pragma = sqlcipher_sqlite3_mprintf("PRAGMA cipher_default_kdf_algorithm = %s;", SQLCIPHER_PBKDF2_HMAC_SHA256_LABEL);
+ } else if(algorithm == SQLCIPHER_PBKDF2_HMAC_SHA512) {
+ pragma = sqlcipher_sqlite3_mprintf("PRAGMA cipher_default_kdf_algorithm = %s;", SQLCIPHER_PBKDF2_HMAC_SHA512_LABEL);
+ }
+ sqlcipher_vdbe_return_string(pParse, "pragma", pragma, P4_DYNAMIC);
+ }else
+ if( sqlcipher_sqlite3_stricmp(zLeft,"cipher_integrity_check")==0 ){
+ if(ctx) {
+ sqlcipher_codec_ctx_integrity_check(ctx, pParse, "cipher_integrity_check");
+ }
+ } else
+ if( sqlcipher_sqlite3_stricmp(zLeft, "cipher_log_level")==0 && zRight){
+ unsigned int level = SQLCIPHER_LOG_NONE;
+ if(sqlcipher_sqlite3_stricmp(zRight, "ERROR")==0) level = SQLCIPHER_LOG_ERROR;
+ else if(sqlcipher_sqlite3_stricmp(zRight, "WARN" )==0) level = SQLCIPHER_LOG_WARN;
+ else if(sqlcipher_sqlite3_stricmp(zRight, "INFO" )==0) level = SQLCIPHER_LOG_INFO;
+ else if(sqlcipher_sqlite3_stricmp(zRight, "DEBUG")==0) level = SQLCIPHER_LOG_DEBUG;
+ else if(sqlcipher_sqlite3_stricmp(zRight, "TRACE")==0) level = SQLCIPHER_LOG_TRACE;
+ sqlcipher_set_log_level(level);
+ sqlcipher_vdbe_return_string(pParse, "cipher_log_level", sqlcipher_sqlite3_mprintf("%u", level), P4_DYNAMIC);
+ } else
+ if( sqlcipher_sqlite3_stricmp(zLeft, "cipher_log")== 0 && zRight ){
+ char *status = sqlcipher_sqlite3_mprintf("%d", sqlcipher_set_log(zRight));
+ sqlcipher_vdbe_return_string(pParse, "cipher_log", status, P4_DYNAMIC);
+ }else {
+ return 0;
+ }
+ return 1;
+}
+
+/* these constants are used internally within SQLite's pager.c to differentiate between
+ operations on the main database or journal pages. This is important in the context
+ of a rekey operations, where the journal must be written using the original key
+ material (to allow a transactional rollback), while the new database pages are being
+ written with the new key material*/
+#define CODEC_READ_OP 3
+#define CODEC_WRITE_OP 6
+#define CODEC_JOURNAL_OP 7
+
+/*
+ * sqlcipher_sqlite3Codec can be called in multiple modes.
+ * encrypt mode - expected to return a pointer to the
+ * encrypted data without altering pData.
+ * decrypt mode - expected to return a pointer to pData, with
+ * the data decrypted in the input buffer
+ */
+static void* sqlcipher_sqlite3Codec(void *iCtx, void *data, Pgno pgno, int mode) {
+ codec_ctx *ctx = (codec_ctx *) iCtx;
+ int offset = 0, rc = 0;
+ int page_sz = sqlcipher_codec_ctx_get_pagesize(ctx);
+ unsigned char *pData = (unsigned char *) data;
+ void *buffer = sqlcipher_codec_ctx_get_data(ctx);
+ int plaintext_header_sz = sqlcipher_codec_ctx_get_plaintext_header_size(ctx);
+ int cctx = CIPHER_READ_CTX;
+
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "sqlcipher_sqlite3Codec: pgno=%d, mode=%d, page_sz=%d", pgno, mode, page_sz);
+
+#ifdef SQLCIPHER_EXT
+ if(sqlcipher_license_check(ctx) != SQLITE_OK) return NULL;
+#endif
+
+ /* call to derive keys if not present yet */
+ if((rc = sqlcipher_codec_key_derive(ctx)) != SQLITE_OK) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_sqlite3Codec: error occurred during key derivation: %d", rc);
+ sqlcipher_codec_ctx_set_error(ctx, rc);
+ return NULL;
+ }
+
+ /* if the plaintext_header_size is negative that means an invalid size was set via
+ PRAGMA. We can't set the error state on the pager at that point because the pager
+ may not be open yet. However, this is a fatal error state, so abort the codec */
+ if(plaintext_header_sz < 0) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_sqlite3Codec: error invalid plaintext_header_sz: %d", plaintext_header_sz);
+ sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR);
+ return NULL;
+ }
+
+ if(pgno == 1) /* adjust starting pointers in data page for header offset on first page*/
+ offset = plaintext_header_sz ? plaintext_header_sz : FILE_HEADER_SZ;
+
+
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "sqlcipher_sqlite3Codec: switch mode=%d offset=%d", mode, offset);
+ switch(mode) {
+ case CODEC_READ_OP: /* decrypt */
+ if(pgno == 1) /* copy initial part of file header or SQLite magic to buffer */
+ memcpy(buffer, plaintext_header_sz ? pData : (void *) SQLITE_FILE_HEADER, offset);
+
+ rc = sqlcipher_page_cipher(ctx, cctx, pgno, CIPHER_DECRYPT, page_sz - offset, pData + offset, (unsigned char*)buffer + offset);
+#ifdef SQLCIPHER_TEST
+ if((sqlcipher_get_test_flags() & TEST_FAIL_DECRYPT) > 0 && sqlcipher_get_test_fail()) {
+ rc = SQLITE_ERROR;
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "simulating decryption failure for pgno=%d, mode=%d, page_sz=%d\n", pgno, mode, page_sz);
+ }
+#endif
+ if(rc != SQLITE_OK) {
+ /* failure to decrypt a page is considered a permanent error and will render the pager unusable
+ in order to prevent inconsistent data being loaded into page cache */
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_sqlite3Codec: error decrypting page %d data: %d", pgno, rc);
+ sqlcipher_memset((unsigned char*) buffer+offset, 0, page_sz-offset);
+ sqlcipher_codec_ctx_set_error(ctx, rc);
+ }
+ memcpy(pData, buffer, page_sz); /* copy buffer data back to pData and return */
+ return pData;
+ break;
+
+ case CODEC_WRITE_OP: /* encrypt database page, operate on write context and fall through to case 7, so the write context is used*/
+ cctx = CIPHER_WRITE_CTX;
+
+ case CODEC_JOURNAL_OP: /* encrypt journal page, operate on read context use to get the original page data from the database */
+ if(pgno == 1) { /* copy initial part of file header or salt to buffer */
+ void *kdf_salt = NULL;
+ /* retrieve the kdf salt */
+ if((rc = sqlcipher_codec_ctx_get_kdf_salt(ctx, &kdf_salt)) != SQLITE_OK) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_sqlite3Codec: error retrieving salt: %d", rc);
+ sqlcipher_codec_ctx_set_error(ctx, rc);
+ return NULL;
+ }
+ memcpy(buffer, plaintext_header_sz ? pData : kdf_salt, offset);
+ }
+ rc = sqlcipher_page_cipher(ctx, cctx, pgno, CIPHER_ENCRYPT, page_sz - offset, pData + offset, (unsigned char*)buffer + offset);
+#ifdef SQLCIPHER_TEST
+ if((sqlcipher_get_test_flags() & TEST_FAIL_ENCRYPT) > 0 && sqlcipher_get_test_fail()) {
+ rc = SQLITE_ERROR;
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "simulating encryption failure for pgno=%d, mode=%d, page_sz=%d\n", pgno, mode, page_sz);
+ }
+#endif
+ if(rc != SQLITE_OK) {
+ /* failure to encrypt a page is considered a permanent error and will render the pager unusable
+ in order to prevent corrupted pages from being written to the main databased when using WAL */
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_sqlite3Codec: error encrypting page %d data: %d", pgno, rc);
+ sqlcipher_memset((unsigned char*)buffer+offset, 0, page_sz-offset);
+ sqlcipher_codec_ctx_set_error(ctx, rc);
+ return NULL;
+ }
+ return buffer; /* return persistent buffer data, pData remains intact */
+ break;
+
+ default:
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_sqlite3Codec: error unsupported codec mode %d", mode);
+ sqlcipher_codec_ctx_set_error(ctx, SQLITE_ERROR); /* unsupported mode, set error */
+ return pData;
+ break;
+ }
+}
+
+static void sqlcipher_sqlite3FreeCodecArg(void *pCodecArg) {
+ codec_ctx *ctx = (codec_ctx *) pCodecArg;
+ if(pCodecArg == NULL) return;
+ sqlcipher_codec_ctx_free(&ctx); /* wipe and free allocated memory for the context */
+ sqlcipher_deactivate(); /* cleanup related structures, OpenSSL etc, when codec is detatched */
+}
+
+int sqlcipherCodecAttach(sqlcipher_sqlite3* db, int nDb, const void *zKey, int nKey) {
+ struct Db *pDb = &db->aDb[nDb];
+
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "sqlcipherCodecAttach: db=%p, nDb=%d", db, nDb);
+
+ if(nKey && zKey && pDb->pBt) {
+ int rc;
+ Pager *pPager = pDb->pBt->pBt->pPager;
+ sqlcipher_sqlite3_file *fd;
+ codec_ctx *ctx;
+
+ /* check if the sqlcipher_sqlite3_file is open, and if not force handle to NULL */
+ if((fd = sqlcipher_sqlite3PagerFile(pPager))->pMethods == 0) fd = NULL;
+
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "sqlcipherCodecAttach: calling sqlcipher_activate()");
+ sqlcipher_activate(); /* perform internal initialization for sqlcipher */
+
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipherCodecAttach: entering database mutex %p", db->mutex);
+ sqlcipher_sqlite3_mutex_enter(db->mutex);
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipherCodecAttach: entered database mutex %p", db->mutex);
+
+#ifdef SQLCIPHER_EXT
+ if((rc = sqlcipher_sqlite3_set_authorizer(db, sqlcipher_license_authorizer, db)) != SQLITE_OK) {
+ sqlcipher_sqlite3_mutex_leave(db->mutex);
+ return rc;
+ }
+#endif
+
+ /* point the internal codec argument against the contet to be prepared */
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "sqlcipherCodecAttach: calling sqlcipher_codec_ctx_init()");
+ rc = sqlcipher_codec_ctx_init(&ctx, pDb, pDb->pBt->pBt->pPager, zKey, nKey);
+
+ if(rc != SQLITE_OK) {
+ /* initialization failed, do not attach potentially corrupted context */
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipherCodecAttach: context initialization failed forcing error state with rc=%d", rc);
+ /* force an error at the pager level, such that even the upstream caller ignores the return code
+ the pager will be in an error state and will process no further operations */
+ sqlcipher_sqlite3pager_error(pPager, rc);
+ pDb->pBt->pBt->db->errCode = rc;
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipherCodecAttach: leaving database mutex %p (early return on rc=%d)", db->mutex, rc);
+ sqlcipher_sqlite3_mutex_leave(db->mutex);
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipherCodecAttach: left database mutex %p (early return on rc=%d)", db->mutex, rc);
+ return rc;
+ }
+
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "sqlcipherCodecAttach: calling sqlcipherPagerSetCodec()");
+ sqlcipherPagerSetCodec(sqlcipher_sqlite3BtreePager(pDb->pBt), sqlcipher_sqlite3Codec, NULL, sqlcipher_sqlite3FreeCodecArg, (void *) ctx);
+
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "sqlcipherCodecAttach: calling codec_set_btree_to_codec_pagesize()");
+ codec_set_btree_to_codec_pagesize(db, pDb, ctx);
+
+ /* force secure delete. This has the benefit of wiping internal data when deleted
+ and also ensures that all pages are written to disk (i.e. not skipped by
+ sqlcipher_sqlite3PagerDontWrite optimizations) */
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "sqlcipherCodecAttach: calling sqlcipher_sqlite3BtreeSecureDelete()");
+ sqlcipher_sqlite3BtreeSecureDelete(pDb->pBt, 1);
+
+ /* if fd is null, then this is an in-memory database and
+ we dont' want to overwrite the AutoVacuum settings
+ if not null, then set to the default */
+ if(fd != NULL) {
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "sqlcipherCodecAttach: calling sqlcipher_sqlite3BtreeSetAutoVacuum()");
+ sqlcipher_sqlite3BtreeSetAutoVacuum(pDb->pBt, SQLITE_DEFAULT_AUTOVACUUM);
+ }
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipherCodecAttach: leaving database mutex %p", db->mutex);
+ sqlcipher_sqlite3_mutex_leave(db->mutex);
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipherCodecAttach: left database mutex %p", db->mutex);
+ }
+ return SQLITE_OK;
+}
+
+int sqlcipher_find_db_index(sqlcipher_sqlite3 *db, const char *zDb) {
+ int db_index;
+ if(zDb == NULL){
+ return 0;
+ }
+ for(db_index = 0; db_index < db->nDb; db_index++) {
+ struct Db *pDb = &db->aDb[db_index];
+ if(strcmp(pDb->zDbSName, zDb) == 0) {
+ return db_index;
+ }
+ }
+ return 0;
+}
+
+SQLITE_API void sqlcipher_sqlite3_activate_see(const char* in) {
+ /* do nothing, security enhancements are always active */
+}
+
+SQLITE_API int sqlcipher_sqlite3_key(sqlcipher_sqlite3 *db, const void *pKey, int nKey) {
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "sqlcipher_sqlite3_key: db=%p", db);
+ return sqlcipher_sqlite3_key_v2(db, "main", pKey, nKey);
+}
+
+SQLITE_API int sqlcipher_sqlite3_key_v2(sqlcipher_sqlite3 *db, const char *zDb, const void *pKey, int nKey) {
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "sqlcipher_sqlite3_key_v2: db=%p zDb=%s", db, zDb);
+ /* attach key if db and pKey are not null and nKey is > 0 */
+ if(db && pKey && nKey) {
+ int db_index = sqlcipher_find_db_index(db, zDb);
+ return sqlcipherCodecAttach(db, db_index, pKey, nKey);
+ }
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_sqlite3_key_v2: no key provided");
+ return SQLITE_ERROR;
+}
+
+SQLITE_API int sqlcipher_sqlite3_rekey(sqlcipher_sqlite3 *db, const void *pKey, int nKey) {
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "sqlcipher_sqlite3_rekey: db=%p", db);
+ return sqlcipher_sqlite3_rekey_v2(db, "main", pKey, nKey);
+}
+
+/* sqlcipher_sqlite3_rekey_v2
+** Given a database, this will reencrypt the database using a new key.
+** There is only one possible modes of operation - to encrypt a database
+** that is already encrpyted. If the database is not already encrypted
+** this should do nothing
+** The proposed logic for this function follows:
+** 1. Determine if the database is already encryptped
+** 2. If there is NOT already a key present do nothing
+** 3. If there is a key present, re-encrypt the database with the new key
+*/
+SQLITE_API int sqlcipher_sqlite3_rekey_v2(sqlcipher_sqlite3 *db, const char *zDb, const void *pKey, int nKey) {
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "sqlcipher_sqlite3_rekey_v2: db=%p zDb=%s", db, zDb);
+ if(db && pKey && nKey) {
+ int db_index = sqlcipher_find_db_index(db, zDb);
+ struct Db *pDb = &db->aDb[db_index];
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "sqlcipher_sqlite3_rekey_v2: database zDb=%p db_index:%d", zDb, db_index);
+ if(pDb->pBt) {
+ codec_ctx *ctx;
+ int rc, page_count;
+ Pgno pgno;
+ PgHdr *page;
+ Pager *pPager = pDb->pBt->pBt->pPager;
+
+ ctx = (codec_ctx*) sqlcipherPagerGetCodec(pDb->pBt->pBt->pPager);
+
+ if(ctx == NULL) {
+ /* there was no codec attached to this database, so this should do nothing! */
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_sqlite3_rekey_v2: no codec attached to db, exiting");
+ return SQLITE_OK;
+ }
+
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_sqlite3_rekey_v2: entering database mutex %p", db->mutex);
+ sqlcipher_sqlite3_mutex_enter(db->mutex);
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_sqlite3_rekey_v2: entered database mutex %p", db->mutex);
+
+ codec_set_pass_key(db, db_index, pKey, nKey, CIPHER_WRITE_CTX);
+
+ /* do stuff here to rewrite the database
+ ** 1. Create a transaction on the database
+ ** 2. Iterate through each page, reading it and then writing it.
+ ** 3. If that goes ok then commit and put ctx->rekey into ctx->key
+ ** note: don't deallocate rekey since it may be used in a subsequent iteration
+ */
+ rc = sqlcipher_sqlite3BtreeBeginTrans(pDb->pBt, 1, 0); /* begin write transaction */
+ sqlcipher_sqlite3PagerPagecount(pPager, &page_count);
+ for(pgno = 1; rc == SQLITE_OK && pgno <= (unsigned int)page_count; pgno++) { /* pgno's start at 1 see pager.c:pagerAcquire */
+ if(!sqlcipher_sqlite3pager_is_sj_pgno(pPager, pgno)) { /* skip this page (see pager.c:pagerAcquire for reasoning) */
+ rc = sqlcipher_sqlite3PagerGet(pPager, pgno, &page, 0);
+ if(rc == SQLITE_OK) { /* write page see pager_incr_changecounter for example */
+ rc = sqlcipher_sqlite3PagerWrite(page);
+ if(rc == SQLITE_OK) {
+ sqlcipher_sqlite3PagerUnref(page);
+ } else {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_sqlite3_rekey_v2: error %d occurred writing page %d", rc, pgno);
+ }
+ } else {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_sqlite3_rekey_v2: error %d occurred getting page %d", rc, pgno);
+ }
+ }
+ }
+
+ /* if commit was successful commit and copy the rekey data to current key, else rollback to release locks */
+ if(rc == SQLITE_OK) {
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "sqlcipher_sqlite3_rekey_v2: committing");
+ rc = sqlcipher_sqlite3BtreeCommit(pDb->pBt);
+ sqlcipher_codec_key_copy(ctx, CIPHER_WRITE_CTX);
+ } else {
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "sqlcipher_sqlite3_rekey_v2: rollback");
+ sqlcipher_sqlite3BtreeRollback(pDb->pBt, SQLITE_ABORT_ROLLBACK, 0);
+ }
+
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_sqlite3_rekey_v2: leaving database mutex %p", db->mutex);
+ sqlcipher_sqlite3_mutex_leave(db->mutex);
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_sqlite3_rekey_v2: left database mutex %p", db->mutex);
+ }
+ return SQLITE_OK;
+ }
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_sqlite3_rekey_v2: no key provided");
+ return SQLITE_ERROR;
+}
+
+void sqlcipherCodecGetKey(sqlcipher_sqlite3* db, int nDb, void **zKey, int *nKey) {
+ struct Db *pDb = &db->aDb[nDb];
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "sqlcipherCodecGetKey:db=%p, nDb=%d", db, nDb);
+ if( pDb->pBt ) {
+ codec_ctx *ctx = (codec_ctx*) sqlcipherPagerGetCodec(pDb->pBt->pBt->pPager);
+
+ if(ctx) {
+ /* pass back the keyspec from the codec, unless PRAGMA cipher_store_pass
+ is set or keyspec has not yet been derived, in which case pass
+ back the password key material */
+ sqlcipher_codec_get_keyspec(ctx, zKey, nKey);
+ if(sqlcipher_codec_get_store_pass(ctx) == 1 || *zKey == NULL) {
+ sqlcipher_codec_get_pass(ctx, zKey, nKey);
+ }
+ } else {
+ *zKey = NULL;
+ *nKey = 0;
+ }
+ }
+}
+
+/*
+ * Implementation of an "export" function that allows a caller
+ * to duplicate the main database to an attached database. This is intended
+ * as a conveneince for users who need to:
+ *
+ * 1. migrate from an non-encrypted database to an encrypted database
+ * 2. move from an encrypted database to a non-encrypted database
+ * 3. convert beween the various flavors of encrypted databases.
+ *
+ * This implementation is based heavily on the procedure and code used
+ * in vacuum.c, but is exposed as a function that allows export to any
+ * named attached database.
+ */
+
+/*
+** Finalize a prepared statement. If there was an error, store the
+** text of the error message in *pzErrMsg. Return the result code.
+**
+** Based on vacuumFinalize from vacuum.c
+*/
+static int sqlcipher_finalize(sqlcipher_sqlite3 *db, sqlcipher_sqlite3_stmt *pStmt, char **pzErrMsg){
+ int rc;
+ rc = sqlcipher_sqlite3VdbeFinalize((Vdbe*)pStmt);
+ if( rc ){
+ sqlcipher_sqlite3SetString(pzErrMsg, db, sqlcipher_sqlite3_errmsg(db));
+ }
+ return rc;
+}
+
+/*
+** Execute zSql on database db. Return an error code.
+**
+** Based on execSql from vacuum.c
+*/
+static int sqlcipher_execSql(sqlcipher_sqlite3 *db, char **pzErrMsg, const char *zSql){
+ sqlcipher_sqlite3_stmt *pStmt;
+ VVA_ONLY( int rc; )
+ if( !zSql ){
+ return SQLITE_NOMEM;
+ }
+ if( SQLITE_OK!=sqlcipher_sqlite3_prepare(db, zSql, -1, &pStmt, 0) ){
+ sqlcipher_sqlite3SetString(pzErrMsg, db, sqlcipher_sqlite3_errmsg(db));
+ return sqlcipher_sqlite3_errcode(db);
+ }
+ VVA_ONLY( rc = ) sqlcipher_sqlite3_step(pStmt);
+ assert( rc!=SQLITE_ROW );
+ return sqlcipher_finalize(db, pStmt, pzErrMsg);
+}
+
+/*
+** Execute zSql on database db. The statement returns exactly
+** one column. Execute this as SQL on the same database.
+**
+** Based on execExecSql from vacuum.c
+*/
+static int sqlcipher_execExecSql(sqlcipher_sqlite3 *db, char **pzErrMsg, const char *zSql){
+ sqlcipher_sqlite3_stmt *pStmt;
+ int rc;
+
+ rc = sqlcipher_sqlite3_prepare(db, zSql, -1, &pStmt, 0);
+ if( rc!=SQLITE_OK ) return rc;
+
+ while( SQLITE_ROW==sqlcipher_sqlite3_step(pStmt) ){
+ rc = sqlcipher_execSql(db, pzErrMsg, (char*)sqlcipher_sqlite3_column_text(pStmt, 0));
+ if( rc!=SQLITE_OK ){
+ sqlcipher_finalize(db, pStmt, pzErrMsg);
+ return rc;
+ }
+ }
+
+ return sqlcipher_finalize(db, pStmt, pzErrMsg);
+}
+
+/*
+ * copy database and schema from the main database to an attached database
+ *
+ * Based on sqlcipher_sqlite3RunVacuum from vacuum.c
+*/
+void sqlcipher_exportFunc(sqlcipher_sqlite3_context *context, int argc, sqlcipher_sqlite3_value **argv) {
+ sqlcipher_sqlite3 *db = sqlcipher_sqlite3_context_db_handle(context);
+ const char* targetDb, *sourceDb;
+ int targetDb_idx = 0;
+ u64 saved_flags = db->flags; /* Saved value of the db->flags */
+ u32 saved_mDbFlags = db->mDbFlags; /* Saved value of the db->mDbFlags */
+ int saved_nChange = db->nChange; /* Saved value of db->nChange */
+ int saved_nTotalChange = db->nTotalChange; /* Saved value of db->nTotalChange */
+ u8 saved_mTrace = db->mTrace; /* Saved value of db->mTrace */
+ int rc = SQLITE_OK; /* Return code from service routines */
+ char *zSql = NULL; /* SQL statements */
+ char *pzErrMsg = NULL;
+
+ if(argc != 1 && argc != 2) {
+ rc = SQLITE_ERROR;
+ pzErrMsg = sqlcipher_sqlite3_mprintf("invalid number of arguments (%d) passed to sqlcipher_export", argc);
+ goto end_of_export;
+ }
+
+ if(sqlcipher_sqlite3_value_type(argv[0]) == SQLITE_NULL) {
+ rc = SQLITE_ERROR;
+ pzErrMsg = sqlcipher_sqlite3_mprintf("target database can't be NULL");
+ goto end_of_export;
+ }
+
+ targetDb = (const char*) sqlcipher_sqlite3_value_text(argv[0]);
+ sourceDb = "main";
+
+ if(argc == 2) {
+ if(sqlcipher_sqlite3_value_type(argv[1]) == SQLITE_NULL) {
+ rc = SQLITE_ERROR;
+ pzErrMsg = sqlcipher_sqlite3_mprintf("target database can't be NULL");
+ goto end_of_export;
+ }
+ sourceDb = (char *) sqlcipher_sqlite3_value_text(argv[1]);
+ }
+
+
+ /* if the name of the target is not main, but the index returned is zero
+ there is a mismatch and we should not proceed */
+ targetDb_idx = sqlcipher_find_db_index(db, targetDb);
+ if(targetDb_idx == 0 && targetDb != NULL && sqlcipher_sqlite3_stricmp("main", targetDb) != 0) {
+ rc = SQLITE_ERROR;
+ pzErrMsg = sqlcipher_sqlite3_mprintf("unknown database %s", targetDb);
+ goto end_of_export;
+ }
+ db->init.iDb = targetDb_idx;
+
+ db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks;
+ db->mDbFlags |= DBFLAG_PreferBuiltin | DBFLAG_Vacuum;
+ db->flags &= ~(u64)(SQLITE_ForeignKeys | SQLITE_ReverseOrder | SQLITE_Defensive | SQLITE_CountRows);
+ db->mTrace = 0;
+
+ /* Query the schema of the main database. Create a mirror schema
+ ** in the temporary database.
+ */
+ zSql = sqlcipher_sqlite3_mprintf(
+ "SELECT sql "
+ " FROM %s.sqlite_schema WHERE type='table' AND name!='sqlite_sequence'"
+ " AND rootpage>0"
+ , sourceDb);
+ rc = (zSql == NULL) ? SQLITE_NOMEM : sqlcipher_execExecSql(db, &pzErrMsg, zSql);
+ if( rc!=SQLITE_OK ) goto end_of_export;
+ sqlcipher_sqlite3_free(zSql);
+
+ zSql = sqlcipher_sqlite3_mprintf(
+ "SELECT sql "
+ " FROM %s.sqlite_schema WHERE sql LIKE 'CREATE INDEX %%' "
+ , sourceDb);
+ rc = (zSql == NULL) ? SQLITE_NOMEM : sqlcipher_execExecSql(db, &pzErrMsg, zSql);
+ if( rc!=SQLITE_OK ) goto end_of_export;
+ sqlcipher_sqlite3_free(zSql);
+
+ zSql = sqlcipher_sqlite3_mprintf(
+ "SELECT sql "
+ " FROM %s.sqlite_schema WHERE sql LIKE 'CREATE UNIQUE INDEX %%'"
+ , sourceDb);
+ rc = (zSql == NULL) ? SQLITE_NOMEM : sqlcipher_execExecSql(db, &pzErrMsg, zSql);
+ if( rc!=SQLITE_OK ) goto end_of_export;
+ sqlcipher_sqlite3_free(zSql);
+
+ /* Loop through the tables in the main database. For each, do
+ ** an "INSERT INTO rekey_db.xxx SELECT * FROM main.xxx;" to copy
+ ** the contents to the temporary database.
+ */
+ zSql = sqlcipher_sqlite3_mprintf(
+ "SELECT 'INSERT INTO %s.' || quote(name) "
+ "|| ' SELECT * FROM %s.' || quote(name) || ';'"
+ "FROM %s.sqlite_schema "
+ "WHERE type = 'table' AND name!='sqlite_sequence' "
+ " AND rootpage>0"
+ , targetDb, sourceDb, sourceDb);
+ rc = (zSql == NULL) ? SQLITE_NOMEM : sqlcipher_execExecSql(db, &pzErrMsg, zSql);
+ if( rc!=SQLITE_OK ) goto end_of_export;
+ sqlcipher_sqlite3_free(zSql);
+
+ /* Copy over the contents of the sequence table
+ */
+ zSql = sqlcipher_sqlite3_mprintf(
+ "SELECT 'INSERT INTO %s.' || quote(name) "
+ "|| ' SELECT * FROM %s.' || quote(name) || ';' "
+ "FROM %s.sqlite_schema WHERE name=='sqlite_sequence';"
+ , targetDb, sourceDb, targetDb);
+ rc = (zSql == NULL) ? SQLITE_NOMEM : sqlcipher_execExecSql(db, &pzErrMsg, zSql);
+ if( rc!=SQLITE_OK ) goto end_of_export;
+ sqlcipher_sqlite3_free(zSql);
+
+ /* Copy the triggers, views, and virtual tables from the main database
+ ** over to the temporary database. None of these objects has any
+ ** associated storage, so all we have to do is copy their entries
+ ** from the SQLITE_MASTER table.
+ */
+ zSql = sqlcipher_sqlite3_mprintf(
+ "INSERT INTO %s.sqlite_schema "
+ " SELECT type, name, tbl_name, rootpage, sql"
+ " FROM %s.sqlite_schema"
+ " WHERE type='view' OR type='trigger'"
+ " OR (type='table' AND rootpage=0)"
+ , targetDb, sourceDb);
+ rc = (zSql == NULL) ? SQLITE_NOMEM : sqlcipher_execSql(db, &pzErrMsg, zSql);
+ if( rc!=SQLITE_OK ) goto end_of_export;
+ sqlcipher_sqlite3_free(zSql);
+
+ zSql = NULL;
+end_of_export:
+ db->init.iDb = 0;
+ db->flags = saved_flags;
+ db->mDbFlags = saved_mDbFlags;
+ db->nChange = saved_nChange;
+ db->nTotalChange = saved_nTotalChange;
+ db->mTrace = saved_mTrace;
+
+ if(zSql) sqlcipher_sqlite3_free(zSql);
+
+ if(rc) {
+ if(pzErrMsg != NULL) {
+ sqlcipher_sqlite3_result_error(context, pzErrMsg, -1);
+ sqlcipher_sqlite3DbFree(db, pzErrMsg);
+ } else {
+ sqlcipher_sqlite3_result_error(context, sqlcipher_sqlite3ErrStr(rc), -1);
+ }
+ }
+}
+#endif
+/* END SQLCIPHER */
+
+/************** End of crypto.c **********************************************/
+/************** Begin file crypto_impl.c *************************************/
+/*
+** SQLCipher
+** http://sqlcipher.net
+**
+** Copyright (c) 2008 - 2013, ZETETIC LLC
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** * Neither the name of the ZETETIC LLC nor the
+** names of its contributors may be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY ZETETIC LLC ''AS IS'' AND ANY
+** EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+** DISCLAIMED. IN NO EVENT SHALL ZETETIC LLC BE LIABLE FOR ANY
+** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**
+*/
+/* BEGIN SQLCIPHER */
+#ifdef SQLITE_HAS_CODEC
+
+/* #include "sqlcipher.h" */
+/* #include "crypto.h" */
+
+#ifdef SQLCIPHER_TEST
+static volatile unsigned int cipher_test_flags = 0;
+unsigned int sqlcipher_get_test_flags() {
+ return cipher_test_flags;
+}
+void sqlcipher_set_test_flags(unsigned int flags) {
+ cipher_test_flags = flags;
+}
+
+static volatile int cipher_test_rand = 0;
+int sqlcipher_get_test_rand() {
+ return cipher_test_rand;
+}
+void sqlcipher_set_test_rand(int rand) {
+ cipher_test_rand = rand;
+}
+int sqlcipher_get_test_fail() {
+ int x;
+
+ /* if cipher_test_rand is not set to a non-zero value always fail (return true) */
+ if (cipher_test_rand == 0) return 1;
+
+ sqlcipher_sqlite3_randomness(sizeof(x), &x);
+ return ((x % cipher_test_rand) == 0);
+}
+#endif
+
+/* Generate code to return a string value */
+
+static volatile unsigned int default_flags = DEFAULT_CIPHER_FLAGS;
+static volatile unsigned char hmac_salt_mask = HMAC_SALT_MASK;
+static volatile int default_kdf_iter = PBKDF2_ITER;
+static volatile int default_page_size = 4096;
+static volatile int default_plaintext_header_sz = 0;
+static volatile int default_hmac_algorithm = SQLCIPHER_HMAC_SHA512;
+static volatile int default_kdf_algorithm = SQLCIPHER_PBKDF2_HMAC_SHA512;
+static volatile int sqlcipher_mem_security_on = 0;
+static volatile int sqlcipher_mem_executed = 0;
+static volatile int sqlcipher_mem_initialized = 0;
+static volatile unsigned int sqlcipher_activate_count = 0;
+static volatile sqlcipher_sqlite3_mem_methods default_mem_methods;
+static sqlcipher_provider *default_provider = NULL;
+
+static sqlcipher_sqlite3_mutex* sqlcipher_static_mutex[SQLCIPHER_MUTEX_COUNT];
+static FILE* sqlcipher_log_file = NULL;
+static volatile int sqlcipher_log_logcat = 0;
+static volatile unsigned int sqlcipher_log_level = SQLCIPHER_LOG_NONE;
+
+sqlcipher_sqlite3_mutex* sqlcipher_mutex(int mutex) {
+ if(mutex < 0 || mutex >= SQLCIPHER_MUTEX_COUNT) return NULL;
+ return sqlcipher_static_mutex[mutex];
+}
+
+static int sqlcipher_mem_init(void *pAppData) {
+ return default_mem_methods.xInit(pAppData);
+}
+static void sqlcipher_mem_shutdown(void *pAppData) {
+ default_mem_methods.xShutdown(pAppData);
+}
+static void *sqlcipher_mem_malloc(int n) {
+ void *ptr = default_mem_methods.xMalloc(n);
+ if(!sqlcipher_mem_executed) sqlcipher_mem_executed = 1;
+ if(sqlcipher_mem_security_on) {
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_mem_malloc: calling sqlcipher_mlock(%p,%d)", ptr, n);
+ sqlcipher_mlock(ptr, n);
+ }
+ return ptr;
+}
+static int sqlcipher_mem_size(void *p) {
+ return default_mem_methods.xSize(p);
+}
+static void sqlcipher_mem_free(void *p) {
+ int sz;
+ if(!sqlcipher_mem_executed) sqlcipher_mem_executed = 1;
+ if(sqlcipher_mem_security_on) {
+ sz = sqlcipher_mem_size(p);
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_mem_free: calling sqlcipher_memset(%p,0,%d) and sqlcipher_munlock(%p, %d)", p, sz, p, sz);
+ sqlcipher_memset(p, 0, sz);
+ sqlcipher_munlock(p, sz);
+ }
+ default_mem_methods.xFree(p);
+}
+static void *sqlcipher_mem_realloc(void *p, int n) {
+ void *new = NULL;
+ int orig_sz = 0;
+ if(sqlcipher_mem_security_on) {
+ orig_sz = sqlcipher_mem_size(p);
+ if (n==0) {
+ sqlcipher_mem_free(p);
+ return NULL;
+ } else if (!p) {
+ return sqlcipher_mem_malloc(n);
+ } else if(n <= orig_sz) {
+ return p;
+ } else {
+ new = sqlcipher_mem_malloc(n);
+ if(new) {
+ memcpy(new, p, orig_sz);
+ sqlcipher_mem_free(p);
+ }
+ return new;
+ }
+ } else {
+ return default_mem_methods.xRealloc(p, n);
+ }
+}
+
+static int sqlcipher_mem_roundup(int n) {
+ return default_mem_methods.xRoundup(n);
+}
+
+static sqlcipher_sqlite3_mem_methods sqlcipher_mem_methods = {
+ sqlcipher_mem_malloc,
+ sqlcipher_mem_free,
+ sqlcipher_mem_realloc,
+ sqlcipher_mem_size,
+ sqlcipher_mem_roundup,
+ sqlcipher_mem_init,
+ sqlcipher_mem_shutdown,
+ 0
+};
+
+void sqlcipher_init_memmethods() {
+ if(sqlcipher_mem_initialized) return;
+ if(sqlcipher_sqlite3_config(SQLITE_CONFIG_GETMALLOC, &default_mem_methods) != SQLITE_OK ||
+ sqlcipher_sqlite3_config(SQLITE_CONFIG_MALLOC, &sqlcipher_mem_methods) != SQLITE_OK) {
+ sqlcipher_mem_security_on = sqlcipher_mem_executed = sqlcipher_mem_initialized = 0;
+ } else {
+ sqlcipher_mem_initialized = 1;
+ }
+}
+
+int sqlcipher_register_provider(sqlcipher_provider *p) {
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_register_provider: entering SQLCIPHER_MUTEX_PROVIDER");
+ sqlcipher_sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER));
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_register_provider: entered SQLCIPHER_MUTEX_PROVIDER");
+
+ if(default_provider != NULL && default_provider != p) {
+ /* only free the current registerd provider if it has been initialized
+ and it isn't a pointer to the same provider passed to the function
+ (i.e. protect against a caller calling register twice for the same provider) */
+ sqlcipher_free(default_provider, sizeof(sqlcipher_provider));
+ }
+ default_provider = p;
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_register_provider: leaving SQLCIPHER_MUTEX_PROVIDER");
+ sqlcipher_sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER));
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_register_provider: left SQLCIPHER_MUTEX_PROVIDER");
+
+ return SQLITE_OK;
+}
+
+/* return a pointer to the currently registered provider. This will
+ allow an application to fetch the current registered provider and
+ make minor changes to it */
+sqlcipher_provider* sqlcipher_get_provider() {
+ return default_provider;
+}
+
+void sqlcipher_activate() {
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_activate: entering static master mutex");
+ sqlcipher_sqlite3_mutex_enter(sqlcipher_sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER));
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_activate: entered static master mutex");
+
+ /* allocate new mutexes */
+ if(sqlcipher_activate_count == 0) {
+ int i;
+ for(i = 0; i < SQLCIPHER_MUTEX_COUNT; i++) {
+ sqlcipher_static_mutex[i] = sqlcipher_sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
+ }
+ }
+
+ /* check to see if there is a provider registered at this point
+ if there no provider registered at this point, register the
+ default provider */
+ if(sqlcipher_get_provider() == NULL) {
+ sqlcipher_provider *p = sqlcipher_malloc(sizeof(sqlcipher_provider));
+#if defined (SQLCIPHER_CRYPTO_CC)
+ extern int sqlcipher_cc_setup(sqlcipher_provider *p);
+ sqlcipher_cc_setup(p);
+#elif defined (SQLCIPHER_CRYPTO_LIBTOMCRYPT)
+ extern int sqlcipher_ltc_setup(sqlcipher_provider *p);
+ sqlcipher_ltc_setup(p);
+#elif defined (SQLCIPHER_CRYPTO_NSS)
+ extern int sqlcipher_nss_setup(sqlcipher_provider *p);
+ sqlcipher_nss_setup(p);
+#elif defined (SQLCIPHER_CRYPTO_OPENSSL)
+ extern int sqlcipher_openssl_setup(sqlcipher_provider *p);
+ sqlcipher_openssl_setup(p);
+#else
+#error "NO DEFAULT SQLCIPHER CRYPTO PROVIDER DEFINED"
+#endif
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "sqlcipher_activate: calling sqlcipher_register_provider(%p)", p);
+#ifdef SQLCIPHER_EXT
+ sqlcipher_ext_provider_setup(p);
+#endif
+ sqlcipher_register_provider(p);
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "sqlcipher_activate: called sqlcipher_register_provider(%p)",p);
+ }
+
+ sqlcipher_activate_count++; /* increment activation count */
+
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_activate: leaving static master mutex");
+ sqlcipher_sqlite3_mutex_leave(sqlcipher_sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER));
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_activate: left static master mutex");
+}
+
+void sqlcipher_deactivate() {
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_deactivate: entering static master mutex");
+ sqlcipher_sqlite3_mutex_enter(sqlcipher_sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER));
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_deactivate: entered static master mutex");
+
+ sqlcipher_activate_count--;
+ /* if no connections are using sqlcipher, cleanup globals */
+ if(sqlcipher_activate_count < 1) {
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_deactivate: entering SQLCIPHER_MUTEX_PROVIDER");
+ sqlcipher_sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER));
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_deactivate: entered SQLCIPHER_MUTEX_PROVIDER");
+
+ if(default_provider != NULL) {
+ sqlcipher_free(default_provider, sizeof(sqlcipher_provider));
+ default_provider = NULL;
+ }
+
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_deactivate: leaving SQLCIPHER_MUTEX_PROVIDER");
+ sqlcipher_sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER));
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_deactivate: left SQLCIPHER_MUTEX_PROVIDER");
+
+#ifdef SQLCIPHER_EXT
+ sqlcipher_ext_provider_destroy();
+#endif
+
+ /* last connection closed, free mutexes */
+ if(sqlcipher_activate_count == 0) {
+ int i;
+ for(i = 0; i < SQLCIPHER_MUTEX_COUNT; i++) {
+ sqlcipher_sqlite3_mutex_free(sqlcipher_static_mutex[i]);
+ }
+ }
+ sqlcipher_activate_count = 0; /* reset activation count */
+ }
+
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_deactivate: leaving static master mutex");
+ sqlcipher_sqlite3_mutex_leave(sqlcipher_sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER));
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_deactivate: left static master mutex");
+}
+
+/* constant time memset using volitile to avoid having the memset
+ optimized out by the compiler.
+ Note: As suggested by Joachim Schipper (joachim.schipper@fox-it.com)
+*/
+void* sqlcipher_memset(void *v, unsigned char value, sqlite_uint64 len) {
+ sqlite_uint64 i = 0;
+ volatile unsigned char *a = v;
+
+ if (v == NULL) return v;
+
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_memset: setting %p[0-%llu]=%d)", a, len, value);
+ for(i = 0; i < len; i++) {
+ a[i] = value;
+ }
+
+ return v;
+}
+
+/* constant time memory check tests every position of a memory segement
+ matches a single value (i.e. the memory is all zeros)
+ returns 0 if match, 1 of no match */
+int sqlcipher_ismemset(const void *v, unsigned char value, sqlite_uint64 len) {
+ const unsigned char *a = v;
+ sqlite_uint64 i = 0, result = 0;
+
+ for(i = 0; i < len; i++) {
+ result |= a[i] ^ value;
+ }
+
+ return (result != 0);
+}
+
+/* constant time memory comparison routine.
+ returns 0 if match, 1 if no match */
+int sqlcipher_memcmp(const void *v0, const void *v1, int len) {
+ const unsigned char *a0 = v0, *a1 = v1;
+ int i = 0, result = 0;
+
+ for(i = 0; i < len; i++) {
+ result |= a0[i] ^ a1[i];
+ }
+
+ return (result != 0);
+}
+
+void sqlcipher_mlock(void *ptr, sqlite_uint64 sz) {
+#ifndef OMIT_MEMLOCK
+#if defined(__unix__) || defined(__APPLE__)
+ int rc;
+ unsigned long pagesize = sysconf(_SC_PAGESIZE);
+ unsigned long offset = (unsigned long) ptr % pagesize;
+
+ if(ptr == NULL || sz == 0) return;
+
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_mem_lock: calling mlock(%p,%lu); _SC_PAGESIZE=%lu", ptr - offset, sz + offset, pagesize);
+ rc = mlock(ptr - offset, sz + offset);
+ if(rc!=0) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_mem_lock: mlock(%p,%lu) returned %d errno=%d", ptr - offset, sz + offset, rc, errno);
+ }
+#elif defined(_WIN32)
+#if !(defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP || WINAPI_FAMILY == WINAPI_FAMILY_APP))
+ int rc;
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_mem_lock: calling VirtualLock(%p,%d)", ptr, sz);
+ rc = VirtualLock(ptr, sz);
+ if(rc==0) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_mem_lock: VirtualLock(%p,%d) returned %d LastError=%d", ptr, sz, rc, GetLastError());
+ }
+#endif
+#endif
+#endif
+}
+
+void sqlcipher_munlock(void *ptr, sqlite_uint64 sz) {
+#ifndef OMIT_MEMLOCK
+#if defined(__unix__) || defined(__APPLE__)
+ int rc;
+ unsigned long pagesize = sysconf(_SC_PAGESIZE);
+ unsigned long offset = (unsigned long) ptr % pagesize;
+
+ if(ptr == NULL || sz == 0) return;
+
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_mem_unlock: calling munlock(%p,%lu)", ptr - offset, sz + offset);
+ rc = munlock(ptr - offset, sz + offset);
+ if(rc!=0) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_mem_unlock: munlock(%p,%lu) returned %d errno=%d", ptr - offset, sz + offset, rc, errno);
+ }
+#elif defined(_WIN32)
+#if !(defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP || WINAPI_FAMILY == WINAPI_FAMILY_APP))
+ int rc;
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_mem_lock: calling VirtualUnlock(%p,%d)", ptr, sz);
+ rc = VirtualUnlock(ptr, sz);
+ if(!rc) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_mem_unlock: VirtualUnlock(%p,%d) returned %d LastError=%d", ptr, sz, rc, GetLastError());
+ }
+#endif
+#endif
+#endif
+}
+
+/**
+ * Free and wipe memory. Uses SQLites internal sqlcipher_sqlite3_free so that memory
+ * can be countend and memory leak detection works in the test suite.
+ * If ptr is not null memory will be freed.
+ * If sz is greater than zero, the memory will be overwritten with zero before it is freed
+ * If sz is > 0, and not compiled with OMIT_MEMLOCK, system will attempt to unlock the
+ * memory segment so it can be paged
+ */
+void sqlcipher_free(void *ptr, sqlite_uint64 sz) {
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_free: calling sqlcipher_memset(%p,0,%llu)", ptr, sz);
+ sqlcipher_memset(ptr, 0, sz);
+ sqlcipher_munlock(ptr, sz);
+ sqlcipher_sqlite3_free(ptr);
+}
+
+/**
+ * allocate memory. Uses sqlite's internall malloc wrapper so memory can be
+ * reference counted and leak detection works. Unless compiled with OMIT_MEMLOCK
+ * attempts to lock the memory pages so sensitive information won't be swapped
+ */
+void* sqlcipher_malloc(sqlite_uint64 sz) {
+ void *ptr;
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_malloc: calling sqlcipher_sqlite3Malloc(%llu)", sz);
+ ptr = sqlcipher_sqlite3Malloc(sz);
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_malloc: calling sqlcipher_memset(%p,0,%llu)", ptr, sz);
+ sqlcipher_memset(ptr, 0, sz);
+ sqlcipher_mlock(ptr, sz);
+ return ptr;
+}
+
+char* sqlcipher_version() {
+#ifdef CIPHER_VERSION_QUALIFIER
+ char *version = sqlcipher_sqlite3_mprintf("%s %s %s", CIPHER_XSTR(CIPHER_VERSION_NUMBER), CIPHER_XSTR(CIPHER_VERSION_QUALIFIER), CIPHER_XSTR(CIPHER_VERSION_BUILD));
+#else
+ char *version = sqlcipher_sqlite3_mprintf("%s %s", CIPHER_XSTR(CIPHER_VERSION_NUMBER), CIPHER_XSTR(CIPHER_VERSION_BUILD));
+#endif
+ return version;
+}
+
+/**
+ * Initialize new cipher_ctx struct. This function will allocate memory
+ * for the cipher context and for the key
+ *
+ * returns SQLITE_OK if initialization was successful
+ * returns SQLITE_NOMEM if an error occured allocating memory
+ */
+static int sqlcipher_cipher_ctx_init(codec_ctx *ctx, cipher_ctx **iCtx) {
+ cipher_ctx *c_ctx;
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "sqlcipher_cipher_ctx_init: allocating context");
+ *iCtx = (cipher_ctx *) sqlcipher_malloc(sizeof(cipher_ctx));
+ c_ctx = *iCtx;
+ if(c_ctx == NULL) return SQLITE_NOMEM;
+
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "sqlcipher_cipher_ctx_init: allocating key");
+ c_ctx->key = (unsigned char *) sqlcipher_malloc(ctx->key_sz);
+
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "sqlcipher_cipher_ctx_init: allocating hmac_key");
+ c_ctx->hmac_key = (unsigned char *) sqlcipher_malloc(ctx->key_sz);
+
+ if(c_ctx->key == NULL) return SQLITE_NOMEM;
+ if(c_ctx->hmac_key == NULL) return SQLITE_NOMEM;
+
+ return SQLITE_OK;
+}
+
+/**
+ * Free and wipe memory associated with a cipher_ctx
+ */
+static void sqlcipher_cipher_ctx_free(codec_ctx* ctx, cipher_ctx **iCtx) {
+ cipher_ctx *c_ctx = *iCtx;
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "cipher_ctx_free: iCtx=%p", iCtx);
+ sqlcipher_free(c_ctx->key, ctx->key_sz);
+ sqlcipher_free(c_ctx->hmac_key, ctx->key_sz);
+ sqlcipher_free(c_ctx->pass, c_ctx->pass_sz);
+ sqlcipher_free(c_ctx->keyspec, ctx->keyspec_sz);
+ sqlcipher_free(c_ctx, sizeof(cipher_ctx));
+}
+
+static int sqlcipher_codec_ctx_reserve_setup(codec_ctx *ctx) {
+ int base_reserve = ctx->iv_sz; /* base reserve size will be IV only */
+ int reserve = base_reserve;
+
+ ctx->hmac_sz = ctx->provider->get_hmac_sz(ctx->provider_ctx, ctx->hmac_algorithm);
+
+ if(sqlcipher_codec_ctx_get_use_hmac(ctx))
+ reserve += ctx->hmac_sz; /* if reserve will include hmac, update that size */
+
+ /* calculate the amount of reserve needed in even increments of the cipher block size */
+ reserve = ((reserve % ctx->block_sz) == 0) ? reserve :
+ ((reserve / ctx->block_sz) + 1) * ctx->block_sz;
+
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "sqlcipher_codec_ctx_reserve_setup: base_reserve=%d block_sz=%d md_size=%d reserve=%d",
+ base_reserve, ctx->block_sz, ctx->hmac_sz, reserve);
+
+ ctx->reserve_sz = reserve;
+
+ return SQLITE_OK;
+}
+
+/**
+ * Compare one cipher_ctx to another.
+ *
+ * returns 0 if all the parameters (except the derived key data) are the same
+ * returns 1 otherwise
+ */
+static int sqlcipher_cipher_ctx_cmp(cipher_ctx *c1, cipher_ctx *c2) {
+ int are_equal = (
+ c1->pass_sz == c2->pass_sz
+ && (
+ c1->pass == c2->pass
+ || !sqlcipher_memcmp((const unsigned char*)c1->pass,
+ (const unsigned char*)c2->pass,
+ c1->pass_sz)
+ ));
+
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "sqlcipher_cipher_ctx_cmp: c1=%p c2=%p sqlcipher_memcmp(c1->pass, c2_pass)=%d are_equal=%d",
+ c1, c2,
+ (c1->pass == NULL || c2->pass == NULL) ?
+ -1 :
+ sqlcipher_memcmp(
+ (const unsigned char*)c1->pass,
+ (const unsigned char*)c2->pass,
+ c1->pass_sz
+ ),
+ are_equal
+ );
+
+ return !are_equal; /* return 0 if they are the same, 1 otherwise */
+}
+
+/**
+ * Copy one cipher_ctx to another. For instance, assuming that read_ctx is a
+ * fully initialized context, you could copy it to write_ctx and all yet data
+ * and pass information across
+ *
+ * returns SQLITE_OK if initialization was successful
+ * returns SQLITE_NOMEM if an error occured allocating memory
+ */
+static int sqlcipher_cipher_ctx_copy(codec_ctx *ctx, cipher_ctx *target, cipher_ctx *source) {
+ void *key = target->key;
+ void *hmac_key = target->hmac_key;
+
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "sqlcipher_cipher_ctx_copy: target=%p, source=%p", target, source);
+ sqlcipher_free(target->pass, target->pass_sz);
+ sqlcipher_free(target->keyspec, ctx->keyspec_sz);
+ memcpy(target, source, sizeof(cipher_ctx));
+
+ target->key = key; /* restore pointer to previously allocated key data */
+ memcpy(target->key, source->key, ctx->key_sz);
+
+ target->hmac_key = hmac_key; /* restore pointer to previously allocated hmac key data */
+ memcpy(target->hmac_key, source->hmac_key, ctx->key_sz);
+
+ if(source->pass && source->pass_sz) {
+ target->pass = sqlcipher_malloc(source->pass_sz);
+ if(target->pass == NULL) return SQLITE_NOMEM;
+ memcpy(target->pass, source->pass, source->pass_sz);
+ }
+ if(source->keyspec) {
+ target->keyspec = sqlcipher_malloc(ctx->keyspec_sz);
+ if(target->keyspec == NULL) return SQLITE_NOMEM;
+ memcpy(target->keyspec, source->keyspec, ctx->keyspec_sz);
+ }
+ return SQLITE_OK;
+}
+
+/**
+ * Set the keyspec for the cipher_ctx
+ *
+ * returns SQLITE_OK if assignment was successfull
+ * returns SQLITE_NOMEM if an error occured allocating memory
+ */
+static int sqlcipher_cipher_ctx_set_keyspec(codec_ctx *ctx, cipher_ctx *c_ctx, const unsigned char *key) {
+ /* free, zero existing pointers and size */
+ sqlcipher_free(c_ctx->keyspec, ctx->keyspec_sz);
+ c_ctx->keyspec = NULL;
+
+ c_ctx->keyspec = sqlcipher_malloc(ctx->keyspec_sz);
+ if(c_ctx->keyspec == NULL) return SQLITE_NOMEM;
+
+ c_ctx->keyspec[0] = 'x';
+ c_ctx->keyspec[1] = '\'';
+ cipher_bin2hex(key, ctx->key_sz, c_ctx->keyspec + 2);
+ cipher_bin2hex(ctx->kdf_salt, ctx->kdf_salt_sz, c_ctx->keyspec + (ctx->key_sz * 2) + 2);
+ c_ctx->keyspec[ctx->keyspec_sz - 1] = '\'';
+ return SQLITE_OK;
+}
+
+int sqlcipher_codec_get_store_pass(codec_ctx *ctx) {
+ return ctx->store_pass;
+}
+
+void sqlcipher_codec_set_store_pass(codec_ctx *ctx, int value) {
+ ctx->store_pass = value;
+}
+
+void sqlcipher_codec_get_pass(codec_ctx *ctx, void **zKey, int *nKey) {
+ *zKey = ctx->read_ctx->pass;
+ *nKey = ctx->read_ctx->pass_sz;
+}
+
+static void sqlcipher_set_derive_key(codec_ctx *ctx, int derive) {
+ if(ctx->read_ctx != NULL) ctx->read_ctx->derive_key = 1;
+ if(ctx->write_ctx != NULL) ctx->write_ctx->derive_key = 1;
+}
+
+/**
+ * Set the passphrase for the cipher_ctx
+ *
+ * returns SQLITE_OK if assignment was successfull
+ * returns SQLITE_NOMEM if an error occured allocating memory
+ */
+static int sqlcipher_cipher_ctx_set_pass(cipher_ctx *ctx, const void *zKey, int nKey) {
+ /* free, zero existing pointers and size */
+ sqlcipher_free(ctx->pass, ctx->pass_sz);
+ ctx->pass = NULL;
+ ctx->pass_sz = 0;
+
+ if(zKey && nKey) { /* if new password is provided, copy it */
+ ctx->pass_sz = nKey;
+ ctx->pass = sqlcipher_malloc(nKey);
+ if(ctx->pass == NULL) return SQLITE_NOMEM;
+ memcpy(ctx->pass, zKey, nKey);
+ }
+ return SQLITE_OK;
+}
+
+int sqlcipher_codec_ctx_set_pass(codec_ctx *ctx, const void *zKey, int nKey, int for_ctx) {
+ cipher_ctx *c_ctx = for_ctx ? ctx->write_ctx : ctx->read_ctx;
+ int rc;
+
+ if((rc = sqlcipher_cipher_ctx_set_pass(c_ctx, zKey, nKey)) != SQLITE_OK) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_codec_ctx_set_pass: error %d from sqlcipher_cipher_ctx_set_pass", rc);
+ return rc;
+ }
+
+ c_ctx->derive_key = 1;
+
+ if(for_ctx == 2) {
+ if((rc = sqlcipher_cipher_ctx_copy(ctx, for_ctx ? ctx->read_ctx : ctx->write_ctx, c_ctx)) != SQLITE_OK) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_codec_ctx_set_pass: error %d from sqlcipher_cipher_ctx_copy", rc);
+ return rc;
+ }
+ }
+
+ return SQLITE_OK;
+}
+
+const char* sqlcipher_codec_ctx_get_cipher(codec_ctx *ctx) {
+ return ctx->provider->get_cipher(ctx->provider_ctx);
+}
+
+/* set the global default KDF iteration */
+void sqlcipher_set_default_kdf_iter(int iter) {
+ default_kdf_iter = iter;
+}
+
+int sqlcipher_get_default_kdf_iter() {
+ return default_kdf_iter;
+}
+
+int sqlcipher_codec_ctx_set_kdf_iter(codec_ctx *ctx, int kdf_iter) {
+ ctx->kdf_iter = kdf_iter;
+ sqlcipher_set_derive_key(ctx, 1);
+ return SQLITE_OK;
+}
+
+int sqlcipher_codec_ctx_get_kdf_iter(codec_ctx *ctx) {
+ return ctx->kdf_iter;
+}
+
+int sqlcipher_codec_ctx_set_fast_kdf_iter(codec_ctx *ctx, int fast_kdf_iter) {
+ ctx->fast_kdf_iter = fast_kdf_iter;
+ sqlcipher_set_derive_key(ctx, 1);
+ return SQLITE_OK;
+}
+
+int sqlcipher_codec_ctx_get_fast_kdf_iter(codec_ctx *ctx) {
+ return ctx->fast_kdf_iter;
+}
+
+/* set the global default flag for HMAC */
+void sqlcipher_set_default_use_hmac(int use) {
+ if(use) default_flags |= CIPHER_FLAG_HMAC;
+ else default_flags &= ~CIPHER_FLAG_HMAC;
+}
+
+int sqlcipher_get_default_use_hmac() {
+ return (default_flags & CIPHER_FLAG_HMAC) != 0;
+}
+
+void sqlcipher_set_hmac_salt_mask(unsigned char mask) {
+ hmac_salt_mask = mask;
+}
+
+unsigned char sqlcipher_get_hmac_salt_mask() {
+ return hmac_salt_mask;
+}
+
+/* set the codec flag for whether this individual database should be using hmac */
+int sqlcipher_codec_ctx_set_use_hmac(codec_ctx *ctx, int use) {
+ if(use) {
+ sqlcipher_codec_ctx_set_flag(ctx, CIPHER_FLAG_HMAC);
+ } else {
+ sqlcipher_codec_ctx_unset_flag(ctx, CIPHER_FLAG_HMAC);
+ }
+
+ return sqlcipher_codec_ctx_reserve_setup(ctx);
+}
+
+int sqlcipher_codec_ctx_get_use_hmac(codec_ctx *ctx) {
+ return (ctx->flags & CIPHER_FLAG_HMAC) != 0;
+}
+
+/* the length of plaintext header size must be:
+ * 1. greater than or equal to zero
+ * 2. a multiple of the cipher block size
+ * 3. less than the usable size of the first database page
+ */
+int sqlcipher_set_default_plaintext_header_size(int size) {
+ default_plaintext_header_sz = size;
+ return SQLITE_OK;
+}
+
+int sqlcipher_codec_ctx_set_plaintext_header_size(codec_ctx *ctx, int size) {
+ if(size >= 0 && (size % ctx->block_sz) == 0 && size < (ctx->page_sz - ctx->reserve_sz)) {
+ ctx->plaintext_header_sz = size;
+ return SQLITE_OK;
+ }
+ ctx->plaintext_header_sz = -1;
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_codec_ctx_set_plaintext_header_size: attempt to set invalid plantext_header_size %d", size);
+ return SQLITE_ERROR;
+}
+
+int sqlcipher_get_default_plaintext_header_size() {
+ return default_plaintext_header_sz;
+}
+
+int sqlcipher_codec_ctx_get_plaintext_header_size(codec_ctx *ctx) {
+ return ctx->plaintext_header_sz;
+}
+
+/* manipulate HMAC algorithm */
+int sqlcipher_set_default_hmac_algorithm(int algorithm) {
+ default_hmac_algorithm = algorithm;
+ return SQLITE_OK;
+}
+
+int sqlcipher_codec_ctx_set_hmac_algorithm(codec_ctx *ctx, int algorithm) {
+ ctx->hmac_algorithm = algorithm;
+ return sqlcipher_codec_ctx_reserve_setup(ctx);
+}
+
+int sqlcipher_get_default_hmac_algorithm() {
+ return default_hmac_algorithm;
+}
+
+int sqlcipher_codec_ctx_get_hmac_algorithm(codec_ctx *ctx) {
+ return ctx->hmac_algorithm;
+}
+
+/* manipulate KDF algorithm */
+int sqlcipher_set_default_kdf_algorithm(int algorithm) {
+ default_kdf_algorithm = algorithm;
+ return SQLITE_OK;
+}
+
+int sqlcipher_codec_ctx_set_kdf_algorithm(codec_ctx *ctx, int algorithm) {
+ ctx->kdf_algorithm = algorithm;
+ return SQLITE_OK;
+}
+
+int sqlcipher_get_default_kdf_algorithm() {
+ return default_kdf_algorithm;
+}
+
+int sqlcipher_codec_ctx_get_kdf_algorithm(codec_ctx *ctx) {
+ return ctx->kdf_algorithm;
+}
+
+int sqlcipher_codec_ctx_set_flag(codec_ctx *ctx, unsigned int flag) {
+ ctx->flags |= flag;
+ return SQLITE_OK;
+}
+
+int sqlcipher_codec_ctx_unset_flag(codec_ctx *ctx, unsigned int flag) {
+ ctx->flags &= ~flag;
+ return SQLITE_OK;
+}
+
+int sqlcipher_codec_ctx_get_flag(codec_ctx *ctx, unsigned int flag) {
+ return (ctx->flags & flag) != 0;
+}
+
+void sqlcipher_codec_ctx_set_error(codec_ctx *ctx, int error) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_codec_ctx_set_error: ctx=%p, error=%d", ctx, error);
+ sqlcipher_sqlite3pager_error(ctx->pBt->pBt->pPager, error);
+ ctx->pBt->pBt->db->errCode = error;
+}
+
+int sqlcipher_codec_ctx_get_reservesize(codec_ctx *ctx) {
+ return ctx->reserve_sz;
+}
+
+void* sqlcipher_codec_ctx_get_data(codec_ctx *ctx) {
+ return ctx->buffer;
+}
+
+static int sqlcipher_codec_ctx_init_kdf_salt(codec_ctx *ctx) {
+ sqlcipher_sqlite3_file *fd = sqlcipher_sqlite3PagerFile(ctx->pBt->pBt->pPager);
+
+ if(!ctx->need_kdf_salt) {
+ return SQLITE_OK; /* don't reload salt when not needed */
+ }
+
+ /* read salt from header, if present, otherwise generate a new random salt */
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "sqlcipher_codec_ctx_init_kdf_salt: obtaining salt");
+ if(fd == NULL || fd->pMethods == 0 || sqlcipher_sqlite3OsRead(fd, ctx->kdf_salt, ctx->kdf_salt_sz, 0) != SQLITE_OK) {
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "sqlcipher_codec_ctx_init_kdf_salt: unable to read salt from file header, generating random");
+ if(ctx->provider->random(ctx->provider_ctx, ctx->kdf_salt, ctx->kdf_salt_sz) != SQLITE_OK) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_codec_ctx_init_kdf_salt: error retrieving random bytes from provider");
+ return SQLITE_ERROR;
+ }
+ }
+ ctx->need_kdf_salt = 0;
+ return SQLITE_OK;
+}
+
+int sqlcipher_codec_ctx_set_kdf_salt(codec_ctx *ctx, unsigned char *salt, int size) {
+ if(size >= ctx->kdf_salt_sz) {
+ memcpy(ctx->kdf_salt, salt, ctx->kdf_salt_sz);
+ ctx->need_kdf_salt = 0;
+ return SQLITE_OK;
+ }
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_codec_ctx_set_kdf_salt: attempt to set salt of incorrect size %d", size);
+ return SQLITE_ERROR;
+}
+
+int sqlcipher_codec_ctx_get_kdf_salt(codec_ctx *ctx, void** salt) {
+ int rc = SQLITE_OK;
+ if(ctx->need_kdf_salt) {
+ if((rc = sqlcipher_codec_ctx_init_kdf_salt(ctx)) != SQLITE_OK) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_codec_ctx_get_kdf_salt: error %d from sqlcipher_codec_ctx_init_kdf_salt", rc);
+ }
+ }
+ *salt = ctx->kdf_salt;
+
+ return rc;
+}
+
+void sqlcipher_codec_get_keyspec(codec_ctx *ctx, void **zKey, int *nKey) {
+ *zKey = ctx->read_ctx->keyspec;
+ *nKey = ctx->keyspec_sz;
+}
+
+int sqlcipher_codec_ctx_set_pagesize(codec_ctx *ctx, int size) {
+ if(!((size != 0) && ((size & (size - 1)) == 0)) || size < 512 || size > 65536) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "cipher_page_size not a power of 2 and between 512 and 65536 inclusive");
+ return SQLITE_ERROR;
+ }
+ /* attempt to free the existing page buffer */
+ sqlcipher_free(ctx->buffer,ctx->page_sz);
+ ctx->page_sz = size;
+
+ /* pre-allocate a page buffer of PageSize bytes. This will
+ be used as a persistent buffer for encryption and decryption
+ operations to avoid overhead of multiple memory allocations*/
+ ctx->buffer = sqlcipher_malloc(size);
+ if(ctx->buffer == NULL) return SQLITE_NOMEM;
+
+ return SQLITE_OK;
+}
+
+int sqlcipher_codec_ctx_get_pagesize(codec_ctx *ctx) {
+ return ctx->page_sz;
+}
+
+void sqlcipher_set_default_pagesize(int page_size) {
+ default_page_size = page_size;
+}
+
+int sqlcipher_get_default_pagesize() {
+ return default_page_size;
+}
+
+void sqlcipher_set_mem_security(int on) {
+ /* memory security can only be enabled, not disabled */
+ if(on) {
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "sqlcipher_set_mem_security: on");
+ sqlcipher_mem_security_on = on;
+ }
+}
+
+int sqlcipher_get_mem_security() {
+ /* only report that memory security is enabled if pragma cipher_memory_security is ON and
+ SQLCipher's allocator/deallocator was run at least one timecurrently used */
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "sqlcipher_get_mem_security: sqlcipher_mem_security_on = %d, sqlcipher_mem_executed = %d", sqlcipher_mem_security_on, sqlcipher_mem_executed);
+ return sqlcipher_mem_security_on && sqlcipher_mem_executed;
+}
+
+
+int sqlcipher_codec_ctx_init(codec_ctx **iCtx, Db *pDb, Pager *pPager, const void *zKey, int nKey) {
+ int rc;
+ codec_ctx *ctx;
+
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "sqlcipher_codec_ctx_init: allocating context");
+
+ *iCtx = sqlcipher_malloc(sizeof(codec_ctx));
+ ctx = *iCtx;
+
+ if(ctx == NULL) return SQLITE_NOMEM;
+
+ ctx->pBt = pDb->pBt; /* assign pointer to database btree structure */
+
+ /* allocate space for salt data. Then read the first 16 bytes
+ directly off the database file. This is the salt for the
+ key derivation function. If we get a short read allocate
+ a new random salt value */
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "sqlcipher_codec_ctx_init: allocating kdf_salt");
+ ctx->kdf_salt_sz = FILE_HEADER_SZ;
+ ctx->kdf_salt = sqlcipher_malloc(ctx->kdf_salt_sz);
+ if(ctx->kdf_salt == NULL) return SQLITE_NOMEM;
+
+ /* allocate space for separate hmac salt data. We want the
+ HMAC derivation salt to be different than the encryption
+ key derivation salt */
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "sqlcipher_codec_ctx_init: allocating hmac_kdf_salt");
+ ctx->hmac_kdf_salt = sqlcipher_malloc(ctx->kdf_salt_sz);
+ if(ctx->hmac_kdf_salt == NULL) return SQLITE_NOMEM;
+
+ /* setup default flags */
+ ctx->flags = default_flags;
+
+ /* defer attempt to read KDF salt until first use */
+ ctx->need_kdf_salt = 1;
+
+ /* setup the crypto provider */
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "sqlcipher_codec_ctx_init: allocating provider");
+ ctx->provider = (sqlcipher_provider *) sqlcipher_malloc(sizeof(sqlcipher_provider));
+ if(ctx->provider == NULL) return SQLITE_NOMEM;
+
+ /* make a copy of the provider to be used for the duration of the context */
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_codec_ctx_init: entering SQLCIPHER_MUTEX_PROVIDER");
+ sqlcipher_sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER));
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_codec_ctx_init: entered SQLCIPHER_MUTEX_PROVIDER");
+
+ memcpy(ctx->provider, default_provider, sizeof(sqlcipher_provider));
+
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_codec_ctx_init: leaving SQLCIPHER_MUTEX_PROVIDER");
+ sqlcipher_sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER));
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_codec_ctx_init: left SQLCIPHER_MUTEX_PROVIDER");
+
+ if((rc = ctx->provider->ctx_init(&ctx->provider_ctx)) != SQLITE_OK) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_codec_ctx_init: error %d returned from ctx_init", rc);
+ return rc;
+ }
+
+ ctx->key_sz = ctx->provider->get_key_sz(ctx->provider_ctx);
+ ctx->iv_sz = ctx->provider->get_iv_sz(ctx->provider_ctx);
+ ctx->block_sz = ctx->provider->get_block_sz(ctx->provider_ctx);
+
+ /* establic the size for a hex-formated key specification, containing the
+ raw encryption key and the salt used to generate it format. will be x'hexkey...hexsalt'
+ so oversize by 3 bytes */
+ ctx->keyspec_sz = ((ctx->key_sz + ctx->kdf_salt_sz) * 2) + 3;
+
+ /*
+ Always overwrite page size and set to the default because the first page of the database
+ in encrypted and thus sqlite can't effectively determine the pagesize. this causes an issue in
+ cases where bytes 16 & 17 of the page header are a power of 2 as reported by John Lehman
+ */
+ if((rc = sqlcipher_codec_ctx_set_pagesize(ctx, default_page_size)) != SQLITE_OK) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_codec_ctx_init: error %d returned from sqlcipher_codec_ctx_set_pagesize with %d", rc, default_page_size);
+ return rc;
+ }
+
+ /* establish settings for the KDF iterations and fast (HMAC) KDF iterations */
+ if((rc = sqlcipher_codec_ctx_set_kdf_iter(ctx, default_kdf_iter)) != SQLITE_OK) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_codec_ctx_init: error %d setting default_kdf_iter %d", rc, default_kdf_iter);
+ return rc;
+ }
+
+ if((rc = sqlcipher_codec_ctx_set_fast_kdf_iter(ctx, FAST_PBKDF2_ITER)) != SQLITE_OK) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_codec_ctx_init: error %d setting fast_kdf_iter to %d", rc, FAST_PBKDF2_ITER);
+ return rc;
+ }
+
+ /* set the default HMAC and KDF algorithms which will determine the reserve size */
+ if((rc = sqlcipher_codec_ctx_set_hmac_algorithm(ctx, default_hmac_algorithm)) != SQLITE_OK) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_codec_ctx_init: error %d setting sqlcipher_codec_ctx_set_hmac_algorithm with %d", rc, default_hmac_algorithm);
+ return rc;
+ }
+
+ /* Note that use_hmac is a special case that requires recalculation of page size
+ so we call set_use_hmac to perform setup */
+ if((rc = sqlcipher_codec_ctx_set_use_hmac(ctx, default_flags & CIPHER_FLAG_HMAC)) != SQLITE_OK) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_codec_ctx_init: error %d setting use_hmac %d", rc, default_flags & CIPHER_FLAG_HMAC);
+ return rc;
+ }
+
+ if((rc = sqlcipher_codec_ctx_set_kdf_algorithm(ctx, default_kdf_algorithm)) != SQLITE_OK) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_codec_ctx_init: error %d setting sqlcipher_codec_ctx_set_kdf_algorithm with %d", rc, default_kdf_algorithm);
+ return rc;
+ }
+
+ /* setup the default plaintext header size */
+ if((rc = sqlcipher_codec_ctx_set_plaintext_header_size(ctx, default_plaintext_header_sz)) != SQLITE_OK) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_codec_ctx_init: error %d setting sqlcipher_codec_ctx_set_plaintext_header_size with %d", rc, default_plaintext_header_sz);
+ return rc;
+ }
+
+ /* initialize the read and write sub-contexts. this must happen after key_sz is established */
+ if((rc = sqlcipher_cipher_ctx_init(ctx, &ctx->read_ctx)) != SQLITE_OK) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_codec_ctx_init: error %d initializing read_ctx", rc);
+ return rc;
+ }
+
+ if((rc = sqlcipher_cipher_ctx_init(ctx, &ctx->write_ctx)) != SQLITE_OK) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_codec_ctx_init: error %d initializing write_ctx", rc);
+ return rc;
+ }
+
+ /* set the key material on one of the sub cipher contexts and sync them up */
+ if((rc = sqlcipher_codec_ctx_set_pass(ctx, zKey, nKey, 0)) != SQLITE_OK) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_codec_ctx_init: error %d setting pass key", rc);
+ return rc;
+ }
+
+ if((rc = sqlcipher_cipher_ctx_copy(ctx, ctx->write_ctx, ctx->read_ctx)) != SQLITE_OK) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_codec_ctx_init: error %d copying write_ctx to read_ctx", rc);
+ return rc;
+ }
+
+ return SQLITE_OK;
+}
+
+/**
+ * Free and wipe memory associated with a cipher_ctx, including the allocated
+ * read_ctx and write_ctx.
+ */
+void sqlcipher_codec_ctx_free(codec_ctx **iCtx) {
+ codec_ctx *ctx = *iCtx;
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "codec_ctx_free: iCtx=%p", iCtx);
+ sqlcipher_free(ctx->kdf_salt, ctx->kdf_salt_sz);
+ sqlcipher_free(ctx->hmac_kdf_salt, ctx->kdf_salt_sz);
+ sqlcipher_free(ctx->buffer, ctx->page_sz);
+
+ ctx->provider->ctx_free(&ctx->provider_ctx);
+ sqlcipher_free(ctx->provider, sizeof(sqlcipher_provider));
+
+ sqlcipher_cipher_ctx_free(ctx, &ctx->read_ctx);
+ sqlcipher_cipher_ctx_free(ctx, &ctx->write_ctx);
+ sqlcipher_free(ctx, sizeof(codec_ctx));
+}
+
+/** convert a 32bit unsigned integer to little endian byte ordering */
+static void sqlcipher_put4byte_le(unsigned char *p, u32 v) {
+ p[0] = (u8)v;
+ p[1] = (u8)(v>>8);
+ p[2] = (u8)(v>>16);
+ p[3] = (u8)(v>>24);
+}
+
+static int sqlcipher_page_hmac(codec_ctx *ctx, cipher_ctx *c_ctx, Pgno pgno, unsigned char *in, int in_sz, unsigned char *out) {
+ unsigned char pgno_raw[sizeof(pgno)];
+ /* we may convert page number to consistent representation before calculating MAC for
+ compatibility across big-endian and little-endian platforms.
+
+ Note: The public release of sqlcipher 2.0.0 to 2.0.6 had a bug where the bytes of pgno
+ were used directly in the MAC. SQLCipher convert's to little endian by default to preserve
+ backwards compatibility on the most popular platforms, but can optionally be configured
+ to use either big endian or native byte ordering via pragma. */
+
+ if(ctx->flags & CIPHER_FLAG_LE_PGNO) { /* compute hmac using little endian pgno*/
+ sqlcipher_put4byte_le(pgno_raw, pgno);
+ } else if(ctx->flags & CIPHER_FLAG_BE_PGNO) { /* compute hmac using big endian pgno */
+ sqlcipher_sqlite3Put4byte(pgno_raw, pgno); /* sqlcipher_sqlite3Put4byte converts 32bit uint to big endian */
+ } else { /* use native byte ordering */
+ memcpy(pgno_raw, &pgno, sizeof(pgno));
+ }
+
+ /* include the encrypted page data, initialization vector, and page number in HMAC. This will
+ prevent both tampering with the ciphertext, manipulation of the IV, or resequencing otherwise
+ valid pages out of order in a database */
+ return ctx->provider->hmac(
+ ctx->provider_ctx, ctx->hmac_algorithm, c_ctx->hmac_key,
+ ctx->key_sz, in,
+ in_sz, (unsigned char*) &pgno_raw,
+ sizeof(pgno), out);
+}
+
+/*
+ * ctx - codec context
+ * pgno - page number in database
+ * size - size in bytes of input and output buffers
+ * mode - 1 to encrypt, 0 to decrypt
+ * in - pointer to input bytes
+ * out - pouter to output bytes
+ */
+int sqlcipher_page_cipher(codec_ctx *ctx, int for_ctx, Pgno pgno, int mode, int page_sz, unsigned char *in, unsigned char *out) {
+ cipher_ctx *c_ctx = for_ctx ? ctx->write_ctx : ctx->read_ctx;
+ unsigned char *iv_in, *iv_out, *hmac_in, *hmac_out, *out_start;
+ int size;
+
+ /* calculate some required positions into various buffers */
+ size = page_sz - ctx->reserve_sz; /* adjust size to useable size and memset reserve at end of page */
+ iv_out = out + size;
+ iv_in = in + size;
+
+ /* hmac will be written immediately after the initialization vector. the remainder of the page reserve will contain
+ random bytes. note, these pointers are only valid when using hmac */
+ hmac_in = in + size + ctx->iv_sz;
+ hmac_out = out + size + ctx->iv_sz;
+ out_start = out; /* note the original position of the output buffer pointer, as out will be rewritten during encryption */
+
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "sqlcipher_page_cipher: pgno=%d, mode=%d, size=%d", pgno, mode, size);
+ CODEC_HEXDUMP("sqlcipher_page_cipher: input page data", in, page_sz);
+
+ /* the key size should never be zero. If it is, error out. */
+ if(ctx->key_sz == 0) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_page_cipher: error possible context corruption, key_sz is zero for pgno=%d", pgno);
+ goto error;
+ }
+
+ if(mode == CIPHER_ENCRYPT) {
+ /* start at front of the reserve block, write random data to the end */
+ if(ctx->provider->random(ctx->provider_ctx, iv_out, ctx->reserve_sz) != SQLITE_OK) goto error;
+ } else { /* CIPHER_DECRYPT */
+ memcpy(iv_out, iv_in, ctx->iv_sz); /* copy the iv from the input to output buffer */
+ }
+
+ if((ctx->flags & CIPHER_FLAG_HMAC) && (mode == CIPHER_DECRYPT) && !ctx->skip_read_hmac) {
+ if(sqlcipher_page_hmac(ctx, c_ctx, pgno, in, size + ctx->iv_sz, hmac_out) != SQLITE_OK) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_page_cipher: hmac operation on decrypt failed for pgno=%d", pgno);
+ goto error;
+ }
+
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "sqlcipher_page_cipher: comparing hmac on in=%p out=%p hmac_sz=%d", hmac_in, hmac_out, ctx->hmac_sz);
+ if(sqlcipher_memcmp(hmac_in, hmac_out, ctx->hmac_sz) != 0) { /* the hmac check failed */
+ if(sqlcipher_sqlite3BtreeGetAutoVacuum(ctx->pBt) != BTREE_AUTOVACUUM_NONE && sqlcipher_ismemset(in, 0, page_sz) == 0) {
+ /* first check if the entire contents of the page is zeros. If so, this page
+ resulted from a short read (i.e. sqlite attempted to pull a page after the end of the file. these
+ short read failures must be ignored for autovaccum mode to work so wipe the output buffer
+ and return SQLITE_OK to skip the decryption step. */
+ sqlcipher_log(SQLCIPHER_LOG_WARN, "sqlcipher_page_cipher: zeroed page (short read) for pgno %d, encryption but returning SQLITE_OK", pgno);
+ sqlcipher_memset(out, 0, page_sz);
+ return SQLITE_OK;
+ } else {
+ /* if the page memory is not all zeros, it means the there was data and a hmac on the page.
+ since the check failed, the page was either tampered with or corrupted. wipe the output buffer,
+ and return SQLITE_ERROR to the caller */
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_page_cipher: hmac check failed for pgno=%d returning SQLITE_ERROR", pgno);
+ goto error;
+ }
+ }
+ }
+
+ if(ctx->provider->cipher(ctx->provider_ctx, mode, c_ctx->key, ctx->key_sz, iv_out, in, size, out) != SQLITE_OK) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_page_cipher: cipher operation mode=%d failed for pgno=%d returning SQLITE_ERROR", mode, pgno);
+ goto error;
+ };
+
+ if((ctx->flags & CIPHER_FLAG_HMAC) && (mode == CIPHER_ENCRYPT)) {
+ if(sqlcipher_page_hmac(ctx, c_ctx, pgno, out_start, size + ctx->iv_sz, hmac_out) != SQLITE_OK) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_page_cipher: hmac operation on encrypt failed for pgno=%d", pgno);
+ goto error;
+ };
+ }
+
+ CODEC_HEXDUMP("sqlcipher_page_cipher: output page data", out_start, page_sz);
+
+ return SQLITE_OK;
+error:
+ sqlcipher_memset(out, 0, page_sz);
+ return SQLITE_ERROR;
+}
+
+/**
+ * Derive an encryption key for a cipher contex key based on the raw password.
+ *
+ * If the raw key data is formated as x'hex' and there are exactly enough hex chars to fill
+ * the key (i.e 64 hex chars for a 256 bit key) then the key data will be used directly.
+
+ * Else, if the raw key data is formated as x'hex' and there are exactly enough hex chars to fill
+ * the key and the salt (i.e 92 hex chars for a 256 bit key and 16 byte salt) then it will be unpacked
+ * as the key followed by the salt.
+ *
+ * Otherwise, a key data will be derived using PBKDF2
+ *
+ * returns SQLITE_OK if initialization was successful
+ * returns SQLITE_ERROR if the key could't be derived (for instance if pass is NULL or pass_sz is 0)
+ */
+static int sqlcipher_cipher_ctx_key_derive(codec_ctx *ctx, cipher_ctx *c_ctx) {
+ int rc;
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "sqlcipher_cipher_ctx_key_derive: ctx->kdf_salt_sz=%d ctx->kdf_iter=%d ctx->fast_kdf_iter=%d ctx->key_sz=%d",
+ ctx->kdf_salt_sz, ctx->kdf_iter, ctx->fast_kdf_iter, ctx->key_sz);
+
+ if(c_ctx->pass && c_ctx->pass_sz) { /* if key material is present on the context for derivation */
+
+ /* if necessary, initialize the salt from the header or random source */
+ if(ctx->need_kdf_salt) {
+ if((rc = sqlcipher_codec_ctx_init_kdf_salt(ctx)) != SQLITE_OK) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_cipher_ctx_key_derive: error %d from sqlcipher_codec_ctx_init_kdf_salt", rc);
+ return rc;
+ }
+ }
+
+ if (c_ctx->pass_sz == ((ctx->key_sz * 2) + 3) && sqlcipher_sqlite3StrNICmp((const char *)c_ctx->pass ,"x'", 2) == 0 && cipher_isHex(c_ctx->pass + 2, ctx->key_sz * 2)) {
+ int n = c_ctx->pass_sz - 3; /* adjust for leading x' and tailing ' */
+ const unsigned char *z = c_ctx->pass + 2; /* adjust lead offset of x' */
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "cipher_ctx_key_derive: using raw key from hex");
+ cipher_hex2bin(z, n, c_ctx->key);
+ } else if (c_ctx->pass_sz == (((ctx->key_sz + ctx->kdf_salt_sz) * 2) + 3) && sqlcipher_sqlite3StrNICmp((const char *)c_ctx->pass ,"x'", 2) == 0 && cipher_isHex(c_ctx->pass + 2, (ctx->key_sz + ctx->kdf_salt_sz) * 2)) {
+ const unsigned char *z = c_ctx->pass + 2; /* adjust lead offset of x' */
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "cipher_ctx_key_derive: using raw key from hex");
+ cipher_hex2bin(z, (ctx->key_sz * 2), c_ctx->key);
+ cipher_hex2bin(z + (ctx->key_sz * 2), (ctx->kdf_salt_sz * 2), ctx->kdf_salt);
+ } else {
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "cipher_ctx_key_derive: deriving key using full PBKDF2 with %d iterations", ctx->kdf_iter);
+ if(ctx->provider->kdf(ctx->provider_ctx, ctx->kdf_algorithm, c_ctx->pass, c_ctx->pass_sz,
+ ctx->kdf_salt, ctx->kdf_salt_sz, ctx->kdf_iter,
+ ctx->key_sz, c_ctx->key) != SQLITE_OK) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "cipher_ctx_key_derive: error occurred from provider kdf generating encryption key");
+ return SQLITE_ERROR;
+ }
+ }
+
+ /* set the context "keyspec" containing the hex-formatted key and salt to be used when attaching databases */
+ if((rc = sqlcipher_cipher_ctx_set_keyspec(ctx, c_ctx, c_ctx->key)) != SQLITE_OK) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_cipher_ctx_key_derive: error %d from sqlcipher_cipher_ctx_set_keyspec", rc);
+ return rc;
+ }
+
+ /* if this context is setup to use hmac checks, generate a seperate and different
+ key for HMAC. In this case, we use the output of the previous KDF as the input to
+ this KDF run. This ensures a distinct but predictable HMAC key. */
+ if(ctx->flags & CIPHER_FLAG_HMAC) {
+ int i;
+
+ /* start by copying the kdf key into the hmac salt slot
+ then XOR it with the fixed hmac salt defined at compile time
+ this ensures that the salt passed in to derive the hmac key, while
+ easy to derive and publically known, is not the same as the salt used
+ to generate the encryption key */
+ memcpy(ctx->hmac_kdf_salt, ctx->kdf_salt, ctx->kdf_salt_sz);
+ for(i = 0; i < ctx->kdf_salt_sz; i++) {
+ ctx->hmac_kdf_salt[i] ^= hmac_salt_mask;
+ }
+
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "cipher_ctx_key_derive: deriving hmac key from encryption key using PBKDF2 with %d iterations",
+ ctx->fast_kdf_iter);
+
+
+ if(ctx->provider->kdf(ctx->provider_ctx, ctx->kdf_algorithm, c_ctx->key, ctx->key_sz,
+ ctx->hmac_kdf_salt, ctx->kdf_salt_sz, ctx->fast_kdf_iter,
+ ctx->key_sz, c_ctx->hmac_key) != SQLITE_OK) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "cipher_ctx_key_derive: error occurred from provider kdf generating HMAC key");
+ return SQLITE_ERROR;
+ }
+ }
+
+ c_ctx->derive_key = 0;
+ return SQLITE_OK;
+ }
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "cipher_ctx_key_derive: key material is not present on the context for key derivation");
+ return SQLITE_ERROR;
+}
+
+int sqlcipher_codec_key_derive(codec_ctx *ctx) {
+ /* derive key on first use if necessary */
+ if(ctx->read_ctx->derive_key) {
+ if(sqlcipher_cipher_ctx_key_derive(ctx, ctx->read_ctx) != SQLITE_OK) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_codec_key_derive: error occurred deriving read_ctx key");
+ return SQLITE_ERROR;
+ }
+ }
+
+ if(ctx->write_ctx->derive_key) {
+ if(sqlcipher_cipher_ctx_cmp(ctx->write_ctx, ctx->read_ctx) == 0) {
+ /* the relevant parameters are the same, just copy read key */
+ if(sqlcipher_cipher_ctx_copy(ctx, ctx->write_ctx, ctx->read_ctx) != SQLITE_OK) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_codec_key_derive: error occurred copying read_ctx to write_ctx");
+ return SQLITE_ERROR;
+ }
+ } else {
+ if(sqlcipher_cipher_ctx_key_derive(ctx, ctx->write_ctx) != SQLITE_OK) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_codec_key_derive: error occurred deriving write_ctx key");
+ return SQLITE_ERROR;
+ }
+ }
+ }
+
+ /* TODO: wipe and free passphrase after key derivation */
+ if(ctx->store_pass != 1) {
+ sqlcipher_cipher_ctx_set_pass(ctx->read_ctx, NULL, 0);
+ sqlcipher_cipher_ctx_set_pass(ctx->write_ctx, NULL, 0);
+ }
+
+ return SQLITE_OK;
+}
+
+int sqlcipher_codec_key_copy(codec_ctx *ctx, int source) {
+ if(source == CIPHER_READ_CTX) {
+ return sqlcipher_cipher_ctx_copy(ctx, ctx->write_ctx, ctx->read_ctx);
+ } else {
+ return sqlcipher_cipher_ctx_copy(ctx, ctx->read_ctx, ctx->write_ctx);
+ }
+}
+
+const char* sqlcipher_codec_get_cipher_provider(codec_ctx *ctx) {
+ return ctx->provider->get_provider_name(ctx->provider_ctx);
+}
+
+
+static int sqlcipher_check_connection(const char *filename, char *key, int key_sz, char *sql, int *user_version, char** journal_mode) {
+ int rc;
+ sqlcipher_sqlite3 *db = NULL;
+ sqlcipher_sqlite3_stmt *statement = NULL;
+ char *query_journal_mode = "PRAGMA journal_mode;";
+ char *query_user_version = "PRAGMA user_version;";
+
+ rc = sqlcipher_sqlite3_open(filename, &db);
+ if(rc != SQLITE_OK) goto cleanup;
+
+ rc = sqlcipher_sqlite3_key(db, key, key_sz);
+ if(rc != SQLITE_OK) goto cleanup;
+
+ rc = sqlcipher_sqlite3_exec(db, sql, NULL, NULL, NULL);
+ if(rc != SQLITE_OK) goto cleanup;
+
+ /* start by querying the user version.
+ this will fail if the key is incorrect */
+ rc = sqlcipher_sqlite3_prepare(db, query_user_version, -1, &statement, NULL);
+ if(rc != SQLITE_OK) goto cleanup;
+
+ rc = sqlcipher_sqlite3_step(statement);
+ if(rc == SQLITE_ROW) {
+ *user_version = sqlcipher_sqlite3_column_int(statement, 0);
+ } else {
+ goto cleanup;
+ }
+ sqlcipher_sqlite3_finalize(statement);
+
+ rc = sqlcipher_sqlite3_prepare(db, query_journal_mode, -1, &statement, NULL);
+ if(rc != SQLITE_OK) goto cleanup;
+
+ rc = sqlcipher_sqlite3_step(statement);
+ if(rc == SQLITE_ROW) {
+ *journal_mode = sqlcipher_sqlite3_mprintf("%s", sqlcipher_sqlite3_column_text(statement, 0));
+ } else {
+ goto cleanup;
+ }
+ rc = SQLITE_OK;
+ /* cleanup will finalize open statement */
+
+cleanup:
+ if(statement) sqlcipher_sqlite3_finalize(statement);
+ if(db) sqlcipher_sqlite3_close(db);
+ return rc;
+}
+
+int sqlcipher_codec_ctx_integrity_check(codec_ctx *ctx, Parse *pParse, char *column) {
+ Pgno page = 1;
+ int rc = 0;
+ char *result;
+ unsigned char *hmac_out = NULL;
+ sqlcipher_sqlite3_file *fd = sqlcipher_sqlite3PagerFile(ctx->pBt->pBt->pPager);
+ i64 file_sz;
+
+ Vdbe *v = sqlcipher_sqlite3GetVdbe(pParse);
+ sqlcipher_sqlite3VdbeSetNumCols(v, 1);
+ sqlcipher_sqlite3VdbeSetColName(v, 0, COLNAME_NAME, column, SQLITE_STATIC);
+
+ if(fd == NULL || fd->pMethods == 0) {
+ sqlcipher_sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, "database file is undefined", P4_TRANSIENT);
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
+ goto cleanup;
+ }
+
+ if(!(ctx->flags & CIPHER_FLAG_HMAC)) {
+ sqlcipher_sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, "HMAC is not enabled, unable to integrity check", P4_TRANSIENT);
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
+ goto cleanup;
+ }
+
+ if((rc = sqlcipher_codec_key_derive(ctx)) != SQLITE_OK) {
+ sqlcipher_sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, "unable to derive keys", P4_TRANSIENT);
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
+ goto cleanup;
+ }
+
+ sqlcipher_sqlite3OsFileSize(fd, &file_sz);
+ hmac_out = sqlcipher_malloc(ctx->hmac_sz);
+
+ for(page = 1; page <= file_sz / ctx->page_sz; page++) {
+ i64 offset = (page - 1) * ctx->page_sz;
+ int payload_sz = ctx->page_sz - ctx->reserve_sz + ctx->iv_sz;
+ int read_sz = ctx->page_sz;
+
+ /* skip integrity check on PAGER_SJ_PGNO since it will have no valid content */
+ if(sqlcipher_sqlite3pager_is_sj_pgno(ctx->pBt->pBt->pPager, page)) continue;
+
+ if(page==1) {
+ int page1_offset = ctx->plaintext_header_sz ? ctx->plaintext_header_sz : FILE_HEADER_SZ;
+ read_sz = read_sz - page1_offset;
+ payload_sz = payload_sz - page1_offset;
+ offset += page1_offset;
+ }
+
+ sqlcipher_memset(ctx->buffer, 0, ctx->page_sz);
+ sqlcipher_memset(hmac_out, 0, ctx->hmac_sz);
+ if(sqlcipher_sqlite3OsRead(fd, ctx->buffer, read_sz, offset) != SQLITE_OK) {
+ result = sqlcipher_sqlite3_mprintf("error reading %d bytes from file page %d at offset %d", read_sz, page, offset);
+ sqlcipher_sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, result, P4_DYNAMIC);
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
+ } else if(sqlcipher_page_hmac(ctx, ctx->read_ctx, page, ctx->buffer, payload_sz, hmac_out) != SQLITE_OK) {
+ result = sqlcipher_sqlite3_mprintf("HMAC operation failed for page %d", page);
+ sqlcipher_sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, result, P4_DYNAMIC);
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
+ } else if(sqlcipher_memcmp(ctx->buffer + payload_sz, hmac_out, ctx->hmac_sz) != 0) {
+ result = sqlcipher_sqlite3_mprintf("HMAC verification failed for page %d", page);
+ sqlcipher_sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, result, P4_DYNAMIC);
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
+ }
+ }
+
+ if(file_sz % ctx->page_sz != 0) {
+ result = sqlcipher_sqlite3_mprintf("page %d has an invalid size of %lld bytes", page, file_sz - ((file_sz / ctx->page_sz) * ctx->page_sz));
+ sqlcipher_sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, result, P4_DYNAMIC);
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
+ }
+
+cleanup:
+ if(hmac_out != NULL) sqlcipher_free(hmac_out, ctx->hmac_sz);
+ return SQLITE_OK;
+}
+
+int sqlcipher_codec_ctx_migrate(codec_ctx *ctx) {
+ int i, pass_sz, keyspec_sz, nRes, user_version, rc, oflags;
+ Db *pDb = 0;
+ sqlcipher_sqlite3 *db = ctx->pBt->db;
+ const char *db_filename = sqlcipher_sqlite3_db_filename(db, "main");
+ char *set_user_version = NULL, *pass = NULL, *attach_command = NULL, *migrated_db_filename = NULL, *keyspec = NULL, *temp = NULL, *journal_mode = NULL, *set_journal_mode = NULL, *pragma_compat = NULL;
+ Btree *pDest = NULL, *pSrc = NULL;
+ sqlcipher_sqlite3_file *srcfile, *destfile;
+#if defined(_WIN32) || defined(SQLITE_OS_WINRT)
+ LPWSTR w_db_filename = NULL, w_migrated_db_filename = NULL;
+ int w_db_filename_sz = 0, w_migrated_db_filename_sz = 0;
+#endif
+ pass_sz = keyspec_sz = rc = user_version = 0;
+
+ if(!db_filename || sqlcipher_sqlite3Strlen30(db_filename) < 1)
+ goto cleanup; /* exit immediately if this is an in memory database */
+
+ /* pull the provided password / key material off the current codec context */
+ pass_sz = ctx->read_ctx->pass_sz;
+ pass = sqlcipher_malloc(pass_sz+1);
+ memset(pass, 0, pass_sz+1);
+ memcpy(pass, ctx->read_ctx->pass, pass_sz);
+
+ /* Version 4 - current, no upgrade required, so exit immediately */
+ rc = sqlcipher_check_connection(db_filename, pass, pass_sz, "", &user_version, &journal_mode);
+ if(rc == SQLITE_OK){
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "No upgrade required - exiting");
+ goto cleanup;
+ }
+
+ for(i = 3; i > 0; i--) {
+ pragma_compat = sqlcipher_sqlite3_mprintf("PRAGMA cipher_compatibility = %d;", i);
+ rc = sqlcipher_check_connection(db_filename, pass, pass_sz, pragma_compat, &user_version, &journal_mode);
+ if(rc == SQLITE_OK) {
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "Version %d format found", i);
+ goto migrate;
+ }
+ if(pragma_compat) sqlcipher_free(pragma_compat, sqlcipher_sqlite3Strlen30(pragma_compat));
+ pragma_compat = NULL;
+ }
+
+ /* if we exit the loop normally we failed to determine the version, this is an error */
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "Upgrade format not determined");
+ goto handle_error;
+
+migrate:
+
+ temp = sqlcipher_sqlite3_mprintf("%s-migrated", db_filename);
+ /* overallocate migrated_db_filename, because sqlcipher_sqlite3OsOpen will read past the null terminator
+ * to determine whether the filename was URI formatted */
+ migrated_db_filename = sqlcipher_malloc(sqlcipher_sqlite3Strlen30(temp)+2);
+ memcpy(migrated_db_filename, temp, sqlcipher_sqlite3Strlen30(temp));
+ sqlcipher_free(temp, sqlcipher_sqlite3Strlen30(temp));
+
+ attach_command = sqlcipher_sqlite3_mprintf("ATTACH DATABASE '%s' as migrate;", migrated_db_filename, pass);
+ set_user_version = sqlcipher_sqlite3_mprintf("PRAGMA migrate.user_version = %d;", user_version);
+
+ rc = sqlcipher_sqlite3_exec(db, pragma_compat, NULL, NULL, NULL);
+ if(rc != SQLITE_OK){
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "set compatibility mode failed, error code %d", rc);
+ goto handle_error;
+ }
+
+ /* force journal mode to DELETE, we will set it back later if different */
+ rc = sqlcipher_sqlite3_exec(db, "PRAGMA journal_mode = delete;", NULL, NULL, NULL);
+ if(rc != SQLITE_OK){
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "force journal mode DELETE failed, error code %d", rc);
+ goto handle_error;
+ }
+
+ rc = sqlcipher_sqlite3_exec(db, attach_command, NULL, NULL, NULL);
+ if(rc != SQLITE_OK){
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "attach failed, error code %d", rc);
+ goto handle_error;
+ }
+
+ rc = sqlcipher_sqlite3_key_v2(db, "migrate", pass, pass_sz);
+ if(rc != SQLITE_OK){
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "keying attached database failed, error code %d", rc);
+ goto handle_error;
+ }
+
+ rc = sqlcipher_sqlite3_exec(db, "SELECT sqlcipher_export('migrate');", NULL, NULL, NULL);
+ if(rc != SQLITE_OK){
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_export failed, error code %d", rc);
+ goto handle_error;
+ }
+
+#ifdef SQLCIPHER_TEST
+ if((sqlcipher_get_test_flags() & TEST_FAIL_MIGRATE) > 0) {
+ rc = SQLITE_ERROR;
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "simulated migrate failure, error code %d", rc);
+ goto handle_error;
+ }
+#endif
+
+ rc = sqlcipher_sqlite3_exec(db, set_user_version, NULL, NULL, NULL);
+ if(rc != SQLITE_OK){
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "set user version failed, error code %d", rc);
+ goto handle_error;
+ }
+
+ if( !db->autoCommit ){
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "cannot migrate from within a transaction");
+ goto handle_error;
+ }
+ if( db->nVdbeActive>1 ){
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "cannot migrate - SQL statements in progress");
+ goto handle_error;
+ }
+
+ pDest = db->aDb[0].pBt;
+ pDb = &(db->aDb[db->nDb-1]);
+ pSrc = pDb->pBt;
+
+ nRes = sqlcipher_sqlite3BtreeGetRequestedReserve(pSrc);
+ /* unset the BTS_PAGESIZE_FIXED flag to avoid SQLITE_READONLY */
+ pDest->pBt->btsFlags &= ~BTS_PAGESIZE_FIXED;
+ rc = sqlcipher_sqlite3BtreeSetPageSize(pDest, default_page_size, nRes, 0);
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "set btree page size to %d res %d rc %d", default_page_size, nRes, rc);
+ if( rc!=SQLITE_OK ) goto handle_error;
+
+ sqlcipherCodecGetKey(db, db->nDb - 1, (void**)&keyspec, &keyspec_sz);
+ sqlcipherCodecAttach(db, 0, keyspec, keyspec_sz);
+
+ srcfile = sqlcipher_sqlite3PagerFile(pSrc->pBt->pPager);
+ destfile = sqlcipher_sqlite3PagerFile(pDest->pBt->pPager);
+
+ sqlcipher_sqlite3OsClose(srcfile);
+ sqlcipher_sqlite3OsClose(destfile);
+
+#if defined(_WIN32) || defined(SQLITE_OS_WINRT)
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "performing windows MoveFileExA");
+
+ w_db_filename_sz = MultiByteToWideChar(CP_UTF8, 0, (LPCCH) db_filename, -1, NULL, 0);
+ w_db_filename = sqlcipher_malloc(w_db_filename_sz * sizeof(wchar_t));
+ w_db_filename_sz = MultiByteToWideChar(CP_UTF8, 0, (LPCCH) db_filename, -1, (const LPWSTR) w_db_filename, w_db_filename_sz);
+
+ w_migrated_db_filename_sz = MultiByteToWideChar(CP_UTF8, 0, (LPCCH) migrated_db_filename, -1, NULL, 0);
+ w_migrated_db_filename = sqlcipher_malloc(w_migrated_db_filename_sz * sizeof(wchar_t));
+ w_migrated_db_filename_sz = MultiByteToWideChar(CP_UTF8, 0, (LPCCH) migrated_db_filename, -1, (const LPWSTR) w_migrated_db_filename, w_migrated_db_filename_sz);
+
+ if(!MoveFileExW(w_migrated_db_filename, w_db_filename, MOVEFILE_REPLACE_EXISTING)) {
+ rc = SQLITE_ERROR;
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "error occurred while renaming %d", rc);
+ goto handle_error;
+ }
+#else
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "performing POSIX rename");
+ if ((rc = rename(migrated_db_filename, db_filename)) != 0) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "error occurred while renaming %d", rc);
+ goto handle_error;
+ }
+#endif
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "renamed migration database %s to main database %s: %d", migrated_db_filename, db_filename, rc);
+
+ rc = sqlcipher_sqlite3OsOpen(db->pVfs, migrated_db_filename, srcfile, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_MAIN_DB, &oflags);
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "reopened migration database: %d", rc);
+ if( rc!=SQLITE_OK ) goto handle_error;
+
+ rc = sqlcipher_sqlite3OsOpen(db->pVfs, db_filename, destfile, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_MAIN_DB, &oflags);
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "reopened main database: %d", rc);
+ if( rc!=SQLITE_OK ) goto handle_error;
+
+ sqlcipher_sqlite3pager_reset(pDest->pBt->pPager);
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "reset pager");
+
+ rc = sqlcipher_sqlite3_exec(db, "DETACH DATABASE migrate;", NULL, NULL, NULL);
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "DETACH DATABASE called %d", rc);
+ if(rc != SQLITE_OK) goto cleanup;
+
+ sqlcipher_sqlite3ResetAllSchemasOfConnection(db);
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "reset all schemas");
+
+ set_journal_mode = sqlcipher_sqlite3_mprintf("PRAGMA journal_mode = %s;", journal_mode);
+ rc = sqlcipher_sqlite3_exec(db, set_journal_mode, NULL, NULL, NULL);
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "%s: %d", set_journal_mode, rc);
+ if( rc!=SQLITE_OK ) goto handle_error;
+
+ goto cleanup;
+
+handle_error:
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "An error occurred attempting to migrate the database - last error %d", rc);
+
+cleanup:
+ if(migrated_db_filename) {
+ int del_rc = sqlcipher_sqlite3OsDelete(db->pVfs, migrated_db_filename, 0);
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "deleted migration database: %d", del_rc);
+ }
+
+ if(pass) sqlcipher_free(pass, pass_sz);
+ if(attach_command) sqlcipher_free(attach_command, sqlcipher_sqlite3Strlen30(attach_command));
+ if(migrated_db_filename) sqlcipher_free(migrated_db_filename, sqlcipher_sqlite3Strlen30(migrated_db_filename));
+ if(set_user_version) sqlcipher_free(set_user_version, sqlcipher_sqlite3Strlen30(set_user_version));
+ if(set_journal_mode) sqlcipher_free(set_journal_mode, sqlcipher_sqlite3Strlen30(set_journal_mode));
+ if(journal_mode) sqlcipher_free(journal_mode, sqlcipher_sqlite3Strlen30(journal_mode));
+ if(pragma_compat) sqlcipher_free(pragma_compat, sqlcipher_sqlite3Strlen30(pragma_compat));
+#if defined(_WIN32) || defined(SQLITE_OS_WINRT)
+ if(w_db_filename) sqlcipher_free(w_db_filename, w_db_filename_sz);
+ if(w_migrated_db_filename) sqlcipher_free(w_migrated_db_filename, w_migrated_db_filename_sz);
+#endif
+ return rc;
+}
+
+int sqlcipher_codec_add_random(codec_ctx *ctx, const char *zRight, int random_sz){
+ const char *suffix = &zRight[random_sz-1];
+ int n = random_sz - 3; /* adjust for leading x' and tailing ' */
+ if (n > 0 &&
+ sqlcipher_sqlite3StrNICmp((const char *)zRight ,"x'", 2) == 0 &&
+ sqlcipher_sqlite3StrNICmp(suffix, "'", 1) == 0 &&
+ n % 2 == 0) {
+ int rc = 0;
+ int buffer_sz = n / 2;
+ unsigned char *random;
+ const unsigned char *z = (const unsigned char *)zRight + 2; /* adjust lead offset of x' */
+ sqlcipher_log(SQLCIPHER_LOG_DEBUG, "sqlcipher_codec_add_random: using raw random blob from hex");
+ random = sqlcipher_malloc(buffer_sz);
+ memset(random, 0, buffer_sz);
+ cipher_hex2bin(z, n, random);
+ rc = ctx->provider->add_random(ctx->provider_ctx, random, buffer_sz);
+ sqlcipher_free(random, buffer_sz);
+ return rc;
+ }
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_codec_add_random: attemt to add random with invalid format");
+ return SQLITE_ERROR;
+}
+
+#if !defined(SQLITE_OMIT_TRACE)
+static int sqlcipher_profile_callback(unsigned int trace, void *file, void *stmt, void *run_time){
+ FILE *f = (FILE*) file;
+ char *fmt = "Elapsed time:%.3f ms - %s\n";
+ double elapsed = (*((sqlcipher_sqlite3_uint64*)run_time))/1000000.0;
+#ifdef __ANDROID__
+ if(f == NULL) {
+ __android_log_print(ANDROID_LOG_DEBUG, "sqlcipher", fmt, elapsed, sqlcipher_sqlite3_sql((sqlcipher_sqlite3_stmt*)stmt));
+ }
+#endif
+ if(f) fprintf(f, fmt, elapsed, sqlcipher_sqlite3_sql((sqlcipher_sqlite3_stmt*)stmt));
+ return SQLITE_OK;
+}
+#endif
+
+int sqlcipher_cipher_profile(sqlcipher_sqlite3 *db, const char *destination){
+#if defined(SQLITE_OMIT_TRACE)
+ return SQLITE_ERROR;
+#else
+ FILE *f = NULL;
+ if(sqlcipher_sqlite3_stricmp(destination, "off") == 0){
+ sqlcipher_sqlite3_trace_v2(db, 0, NULL, NULL); /* disable tracing */
+ } else {
+ if(sqlcipher_sqlite3_stricmp(destination, "stdout") == 0){
+ f = stdout;
+ }else if(sqlcipher_sqlite3_stricmp(destination, "stderr") == 0){
+ f = stderr;
+ }else if(sqlcipher_sqlite3_stricmp(destination, "logcat") == 0){
+ f = NULL; /* file pointer will be NULL indicating logcat on android */
+ }else{
+#if !defined(SQLCIPHER_PROFILE_USE_FOPEN) && (defined(_WIN32) && (__STDC_VERSION__ > 199901L) || defined(SQLITE_OS_WINRT))
+ if(fopen_s(&f, destination, "a") != 0) return SQLITE_ERROR;
+#else
+ if((f = fopen(destination, "a")) == 0) return SQLITE_ERROR;
+#endif
+ }
+ sqlcipher_sqlite3_trace_v2(db, SQLITE_TRACE_PROFILE, sqlcipher_profile_callback, f);
+ }
+ return SQLITE_OK;
+#endif
+}
+
+int sqlcipher_codec_fips_status(codec_ctx *ctx) {
+ return ctx->provider->fips_status(ctx->provider_ctx);
+}
+
+const char* sqlcipher_codec_get_provider_version(codec_ctx *ctx) {
+ return ctx->provider->get_provider_version(ctx->provider_ctx);
+}
+
+#ifndef SQLCIPHER_OMIT_LOG
+/* constants from https://github.com/Alexpux/mingw-w64/blob/master/mingw-w64-crt/misc/gettimeofday.c */
+#define FILETIME_1970 116444736000000000ull /* seconds between 1/1/1601 and 1/1/1970 */
+#define HECTONANOSEC_PER_SEC 10000000ull
+void sqlcipher_log(unsigned int level, const char *message, ...) {
+ va_list params;
+ va_start(params, message);
+
+#ifdef CODEC_DEBUG
+#ifdef __ANDROID__
+ __android_log_vprint(ANDROID_LOG_DEBUG, "sqlcipher", message, params);
+#else
+ vfprintf(stderr, message, params);
+ fprintf(stderr, "\n");
+#endif
+#endif
+
+ if(level > sqlcipher_log_level || (sqlcipher_log_logcat == 0 && sqlcipher_log_file == NULL)) {
+ /* no log target or tag not in included filters */
+ goto end;
+ }
+ if(sqlcipher_log_file != NULL){
+ char buffer[24];
+ struct tm tt;
+ int ms;
+ time_t sec;
+#ifdef _WIN32
+ SYSTEMTIME st;
+ FILETIME ft;
+ GetSystemTime(&st);
+ SystemTimeToFileTime(&st, &ft);
+ sec = (time_t) ((*((sqlite_int64*)&ft) - FILETIME_1970) / HECTONANOSEC_PER_SEC);
+ ms = st.wMilliseconds;
+ localtime_s(&tt, &sec);
+#else
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ sec = tv.tv_sec;
+ ms = tv.tv_usec/1000.0;
+ localtime_r(&sec, &tt);
+#endif
+ if(strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &tt)) {
+ fprintf((FILE*)sqlcipher_log_file, "%s.%03d: ", buffer, ms);
+ vfprintf((FILE*)sqlcipher_log_file, message, params);
+ fprintf((FILE*)sqlcipher_log_file, "\n");
+ }
+ }
+#ifdef __ANDROID__
+ if(sqlcipher_log_logcat) {
+ __android_log_vprint(ANDROID_LOG_DEBUG, "sqlcipher", message, params);
+ }
+#endif
+end:
+ va_end(params);
+}
+#endif
+
+void sqlcipher_set_log_level(unsigned int level) {
+ sqlcipher_log_level = level;
+}
+
+int sqlcipher_set_log(const char *destination){
+#ifdef SQLCIPHER_OMIT_LOG
+ return SQLITE_ERROR;
+#else
+ /* close open trace file if it is not stdout or stderr, then
+ reset trace settings */
+ if(sqlcipher_log_file != NULL && sqlcipher_log_file != stdout && sqlcipher_log_file != stderr) {
+ fclose((FILE*)sqlcipher_log_file);
+ }
+ sqlcipher_log_file = NULL;
+ sqlcipher_log_logcat = 0;
+
+ if(sqlcipher_sqlite3_stricmp(destination, "logcat") == 0){
+ sqlcipher_log_logcat = 1;
+ } else if(sqlcipher_sqlite3_stricmp(destination, "stdout") == 0){
+ sqlcipher_log_file = stdout;
+ }else if(sqlcipher_sqlite3_stricmp(destination, "stderr") == 0){
+ sqlcipher_log_file = stderr;
+ }else if(sqlcipher_sqlite3_stricmp(destination, "off") != 0){
+#if !defined(SQLCIPHER_PROFILE_USE_FOPEN) && (defined(_WIN32) && (__STDC_VERSION__ > 199901L) || defined(SQLITE_OS_WINRT))
+ if(fopen_s(&sqlcipher_log_file, destination, "a") != 0) return SQLITE_ERROR;
+#else
+ if((sqlcipher_log_file = fopen(destination, "a")) == 0) return SQLITE_ERROR;
+#endif
+ }
+ sqlcipher_log(SQLCIPHER_LOG_INFO, "sqlcipher_set_log: set log to %s", destination);
+ return SQLITE_OK;
+#endif
+}
+
+#endif
+/* END SQLCIPHER */
+
+/************** End of crypto_impl.c *****************************************/
+/************** Begin file crypto_libtomcrypt.c ******************************/
+/*
+** SQLCipher
+** http://sqlcipher.net
+**
+** Copyright (c) 2008 - 2013, ZETETIC LLC
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** * Neither the name of the ZETETIC LLC nor the
+** names of its contributors may be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY ZETETIC LLC ''AS IS'' AND ANY
+** EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+** DISCLAIMED. IN NO EVENT SHALL ZETETIC LLC BE LIABLE FOR ANY
+** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**
+*/
+/* BEGIN SQLCIPHER */
+#ifdef SQLITE_HAS_CODEC
+#ifdef SQLCIPHER_CRYPTO_LIBTOMCRYPT
+/* #include "sqliteInt.h" */
+/* #include "sqlcipher.h" */
+#include <tomcrypt.h>
+
+#define FORTUNA_MAX_SZ 32
+static prng_state prng;
+static volatile unsigned int ltc_init = 0;
+static volatile unsigned int ltc_ref_count = 0;
+
+#define LTC_CIPHER "rijndael"
+
+static int sqlcipher_ltc_add_random(void *ctx, void *buffer, int length) {
+ int rc = 0;
+ int data_to_read = length;
+ int block_sz = data_to_read < FORTUNA_MAX_SZ ? data_to_read : FORTUNA_MAX_SZ;
+ const unsigned char * data = (const unsigned char *)buffer;
+
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_ltc_add_random: entering SQLCIPHER_MUTEX_PROVIDER_RAND");
+ sqlcipher_sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_RAND));
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_ltc_add_random: entered SQLCIPHER_MUTEX_PROVIDER_RAND");
+
+ while(data_to_read > 0){
+ rc = fortuna_add_entropy(data, block_sz, &prng);
+ rc = rc != CRYPT_OK ? SQLITE_ERROR : SQLITE_OK;
+ if(rc != SQLITE_OK){
+ break;
+ }
+ data_to_read -= block_sz;
+ data += block_sz;
+ block_sz = data_to_read < FORTUNA_MAX_SZ ? data_to_read : FORTUNA_MAX_SZ;
+ }
+ fortuna_ready(&prng);
+
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_ltc_add_random: leaving SQLCIPHER_MUTEX_PROVIDER_RAND");
+ sqlcipher_sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_RAND));
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_ltc_add_random: left SQLCIPHER_MUTEX_PROVIDER_RAND");
+
+ return rc;
+}
+
+static int sqlcipher_ltc_activate(void *ctx) {
+ unsigned char random_buffer[FORTUNA_MAX_SZ];
+
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_ltc_activate: entering SQLCIPHER_MUTEX_PROVIDER_ACTIVATE");
+ sqlcipher_sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE));
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_ltc_activate: entered SQLCIPHER_MUTEX_PROVIDER_ACTIVATE");
+
+ sqlcipher_memset(random_buffer, 0, FORTUNA_MAX_SZ);
+ if(ltc_init == 0) {
+ if(register_prng(&fortuna_desc) < 0) return SQLITE_ERROR;
+ if(register_cipher(&rijndael_desc) < 0) return SQLITE_ERROR;
+ if(register_hash(&sha512_desc) < 0) return SQLITE_ERROR;
+ if(register_hash(&sha256_desc) < 0) return SQLITE_ERROR;
+ if(register_hash(&sha1_desc) < 0) return SQLITE_ERROR;
+ if(fortuna_start(&prng) != CRYPT_OK) {
+ return SQLITE_ERROR;
+ }
+
+ ltc_init = 1;
+ }
+ ltc_ref_count++;
+
+#ifndef SQLCIPHER_TEST
+ sqlcipher_sqlite3_randomness(FORTUNA_MAX_SZ, random_buffer);
+#endif
+
+ if(sqlcipher_ltc_add_random(ctx, random_buffer, FORTUNA_MAX_SZ) != SQLITE_OK) {
+ return SQLITE_ERROR;
+ }
+ sqlcipher_memset(random_buffer, 0, FORTUNA_MAX_SZ);
+
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_ltc_activate: leaving SQLCIPHER_MUTEX_PROVIDER_ACTIVATE");
+ sqlcipher_sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE));
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_ltc_activate: left SQLCIPHER_MUTEX_PROVIDER_ACTIVATE");
+
+ return SQLITE_OK;
+}
+
+static int sqlcipher_ltc_deactivate(void *ctx) {
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_ltc_deactivate: entering SQLCIPHER_MUTEX_PROVIDER_ACTIVATE");
+ sqlcipher_sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE));
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_ltc_deactivate: entered SQLCIPHER_MUTEX_PROVIDER_ACTIVATE");
+
+ ltc_ref_count--;
+ if(ltc_ref_count == 0){
+ fortuna_done(&prng);
+ sqlcipher_memset((void *)&prng, 0, sizeof(prng));
+ }
+
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_ltc_deactivate: leaving SQLCIPHER_MUTEX_PROVIDER_ACTIVATE");
+ sqlcipher_sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE));
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_ltc_deactivate: left SQLCIPHER_MUTEX_PROVIDER_ACTIVATE");
+
+ return SQLITE_OK;
+}
+
+static const char* sqlcipher_ltc_get_provider_name(void *ctx) {
+ return "libtomcrypt";
+}
+
+static const char* sqlcipher_ltc_get_provider_version(void *ctx) {
+ return SCRYPT;
+}
+
+static int sqlcipher_ltc_random(void *ctx, void *buffer, int length) {
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_ltc_random: entering SQLCIPHER_MUTEX_PROVIDER_RAND");
+ sqlcipher_sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_RAND));
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_ltc_random: entered SQLCIPHER_MUTEX_PROVIDER_RAND");
+
+ fortuna_read(buffer, length, &prng);
+
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_ltc_random: leaving SQLCIPHER_MUTEX_PROVIDER_RAND");
+ sqlcipher_sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_RAND));
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_ltc_random: left SQLCIPHER_MUTEX_PROVIDER_RAND");
+
+ return SQLITE_OK;
+}
+
+static int sqlcipher_ltc_hmac(void *ctx, int algorithm, unsigned char *hmac_key, int key_sz, unsigned char *in, int in_sz, unsigned char *in2, int in2_sz, unsigned char *out) {
+ int rc, hash_idx;
+ hmac_state hmac;
+ unsigned long outlen;
+ switch(algorithm) {
+ case SQLCIPHER_HMAC_SHA1:
+ hash_idx = find_hash("sha1");
+ break;
+ case SQLCIPHER_HMAC_SHA256:
+ hash_idx = find_hash("sha256");
+ break;
+ case SQLCIPHER_HMAC_SHA512:
+ hash_idx = find_hash("sha512");
+ break;
+ default:
+ return SQLITE_ERROR;
+ }
+
+ if(hash_idx < 0) return SQLITE_ERROR;
+ outlen = hash_descriptor[hash_idx].hashsize;
+
+ if(in == NULL) return SQLITE_ERROR;
+ if((rc = hmac_init(&hmac, hash_idx, hmac_key, key_sz)) != CRYPT_OK) return SQLITE_ERROR;
+ if((rc = hmac_process(&hmac, in, in_sz)) != CRYPT_OK) return SQLITE_ERROR;
+ if(in2 != NULL && (rc = hmac_process(&hmac, in2, in2_sz)) != CRYPT_OK) return SQLITE_ERROR;
+ if((rc = hmac_done(&hmac, out, &outlen)) != CRYPT_OK) return SQLITE_ERROR;
+ return SQLITE_OK;
+}
+
+static int sqlcipher_ltc_kdf(void *ctx, int algorithm, const unsigned char *pass, int pass_sz, unsigned char* salt, int salt_sz, int workfactor, int key_sz, unsigned char *key) {
+ int rc, hash_idx;
+ unsigned long outlen = key_sz;
+
+ switch(algorithm) {
+ case SQLCIPHER_HMAC_SHA1:
+ hash_idx = find_hash("sha1");
+ break;
+ case SQLCIPHER_HMAC_SHA256:
+ hash_idx = find_hash("sha256");
+ break;
+ case SQLCIPHER_HMAC_SHA512:
+ hash_idx = find_hash("sha512");
+ break;
+ default:
+ return SQLITE_ERROR;
+ }
+ if(hash_idx < 0) return SQLITE_ERROR;
+
+ if((rc = pkcs_5_alg2(pass, pass_sz, salt, salt_sz,
+ workfactor, hash_idx, key, &outlen)) != CRYPT_OK) {
+ return SQLITE_ERROR;
+ }
+ return SQLITE_OK;
+}
+
+static const char* sqlcipher_ltc_get_cipher(void *ctx) {
+ return "aes-256-cbc";
+}
+
+static int sqlcipher_ltc_cipher(void *ctx, int mode, unsigned char *key, int key_sz, unsigned char *iv, unsigned char *in, int in_sz, unsigned char *out) {
+ int rc, cipher_idx;
+ symmetric_CBC cbc;
+
+ if((cipher_idx = find_cipher(LTC_CIPHER)) == -1) return SQLITE_ERROR;
+ if((rc = cbc_start(cipher_idx, iv, key, key_sz, 0, &cbc)) != CRYPT_OK) return SQLITE_ERROR;
+ rc = mode == 1 ? cbc_encrypt(in, out, in_sz, &cbc) : cbc_decrypt(in, out, in_sz, &cbc);
+ if(rc != CRYPT_OK) return SQLITE_ERROR;
+ cbc_done(&cbc);
+ return SQLITE_OK;
+}
+
+static int sqlcipher_ltc_get_key_sz(void *ctx) {
+ int cipher_idx = find_cipher(LTC_CIPHER);
+ return cipher_descriptor[cipher_idx].max_key_length;
+}
+
+static int sqlcipher_ltc_get_iv_sz(void *ctx) {
+ int cipher_idx = find_cipher(LTC_CIPHER);
+ return cipher_descriptor[cipher_idx].block_length;
+}
+
+static int sqlcipher_ltc_get_block_sz(void *ctx) {
+ int cipher_idx = find_cipher(LTC_CIPHER);
+ return cipher_descriptor[cipher_idx].block_length;
+}
+
+static int sqlcipher_ltc_get_hmac_sz(void *ctx, int algorithm) {
+ int hash_idx;
+ switch(algorithm) {
+ case SQLCIPHER_HMAC_SHA1:
+ hash_idx = find_hash("sha1");
+ break;
+ case SQLCIPHER_HMAC_SHA256:
+ hash_idx = find_hash("sha256");
+ break;
+ case SQLCIPHER_HMAC_SHA512:
+ hash_idx = find_hash("sha512");
+ break;
+ default:
+ return 0;
+ }
+
+ if(hash_idx < 0) return 0;
+
+ return hash_descriptor[hash_idx].hashsize;
+}
+
+static int sqlcipher_ltc_ctx_init(void **ctx) {
+ sqlcipher_ltc_activate(NULL);
+ return SQLITE_OK;
+}
+
+static int sqlcipher_ltc_ctx_free(void **ctx) {
+ sqlcipher_ltc_deactivate(&ctx);
+ return SQLITE_OK;
+}
+
+static int sqlcipher_ltc_fips_status(void *ctx) {
+ return 0;
+}
+
+int sqlcipher_ltc_setup(sqlcipher_provider *p) {
+ p->activate = sqlcipher_ltc_activate;
+ p->deactivate = sqlcipher_ltc_deactivate;
+ p->get_provider_name = sqlcipher_ltc_get_provider_name;
+ p->random = sqlcipher_ltc_random;
+ p->hmac = sqlcipher_ltc_hmac;
+ p->kdf = sqlcipher_ltc_kdf;
+ p->cipher = sqlcipher_ltc_cipher;
+ p->get_cipher = sqlcipher_ltc_get_cipher;
+ p->get_key_sz = sqlcipher_ltc_get_key_sz;
+ p->get_iv_sz = sqlcipher_ltc_get_iv_sz;
+ p->get_block_sz = sqlcipher_ltc_get_block_sz;
+ p->get_hmac_sz = sqlcipher_ltc_get_hmac_sz;
+ p->ctx_init = sqlcipher_ltc_ctx_init;
+ p->ctx_free = sqlcipher_ltc_ctx_free;
+ p->add_random = sqlcipher_ltc_add_random;
+ p->fips_status = sqlcipher_ltc_fips_status;
+ p->get_provider_version = sqlcipher_ltc_get_provider_version;
+ return SQLITE_OK;
+}
+
+#endif
+#endif
+/* END SQLCIPHER */
+
+/************** End of crypto_libtomcrypt.c **********************************/
+/************** Begin file crypto_nss.c **************************************/
+/*
+** SQLCipher
+** http://sqlcipher.net
+**
+** Copyright (c) 2008 - 2013, ZETETIC LLC
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** * Neither the name of the ZETETIC LLC nor the
+** names of its contributors may be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY ZETETIC LLC ''AS IS'' AND ANY
+** EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+** DISCLAIMED. IN NO EVENT SHALL ZETETIC LLC BE LIABLE FOR ANY
+** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**
+*/
+/* BEGIN SQLCIPHER */
+#ifdef SQLITE_HAS_CODEC
+#ifdef SQLCIPHER_CRYPTO_NSS
+/* #include "crypto.h" */
+/* #include "sqlcipher.h" */
+#include <nss/blapit.h>
+#include <nss/nss.h>
+#include <nss/pk11pub.h>
+
+static NSSInitContext* nss_init_context = NULL;
+static unsigned int nss_init_count = 0;
+
+int sqlcipher_nss_setup(sqlcipher_provider *p);
+
+static int sqlcipher_nss_activate(void *ctx) {
+
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_nss_activate: entering SQLCIPHER_MUTEX_PROVIDER_ACTIVATE");
+ sqlcipher_sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE));
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_nss_activate: entered SQLCIPHER_MUTEX_PROVIDER_ACTIVATE");
+ if (nss_init_context == NULL) {
+ nss_init_context = NSS_InitContext("", "", "", "", NULL,
+ NSS_INIT_READONLY | NSS_INIT_NOCERTDB | NSS_INIT_NOMODDB |
+ NSS_INIT_FORCEOPEN | NSS_INIT_OPTIMIZESPACE | NSS_INIT_NOROOTINIT);
+ }
+ nss_init_count++;
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_nss_activate: leaving SQLCIPHER_MUTEX_PROVIDER_ACTIVATE");
+ sqlcipher_sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE));
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_nss_activate: left SQLCIPHER_MUTEX_PROVIDER_ACTIVATE");
+ return SQLITE_OK;
+}
+
+static int sqlcipher_nss_deactivate(void *ctx) {
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_nss_activate: entering SQLCIPHER_MUTEX_PROVIDER_ACTIVATE");
+ sqlcipher_sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE));
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_nss_activate: entered SQLCIPHER_MUTEX_PROVIDER_ACTIVATE");
+
+ nss_init_count--;
+ if (nss_init_count == 0 && nss_init_context != NULL) {
+ NSS_ShutdownContext(nss_init_context);
+ nss_init_context = NULL;
+ }
+
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_nss_activate: leaving SQLCIPHER_MUTEX_PROVIDER_ACTIVATE");
+ sqlcipher_sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE));
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_nss_activate: left SQLCIPHER_MUTEX_PROVIDER_ACTIVATE");
+ return SQLITE_OK;
+}
+
+static int sqlcipher_nss_add_random(void *ctx, void *buffer, int length) {
+ return SQLITE_OK;
+}
+
+/* generate a defined number of random bytes */
+static int sqlcipher_nss_random (void *ctx, void *buffer, int length) {
+ // PK11_GenerateRandom should be thread-safe.
+ return (PK11_GenerateRandom((unsigned char *)buffer, length) == SECSuccess) ? SQLITE_OK : SQLITE_ERROR;
+}
+
+static const char* sqlcipher_nss_get_provider_name(void *ctx) {
+ return "nss";
+}
+
+static const char* sqlcipher_nss_get_provider_version(void *ctx) {
+ return NSS_GetVersion();
+}
+
+static const char* sqlcipher_nss_get_cipher(void *ctx) {
+ return "aes-256-cbc";
+}
+
+static int sqlcipher_nss_get_key_sz(void *ctx) {
+ return AES_256_KEY_LENGTH;
+}
+
+static int sqlcipher_nss_get_iv_sz(void *ctx) {
+ return AES_BLOCK_SIZE;
+}
+
+static int sqlcipher_nss_get_block_sz(void *ctx) {
+ return AES_BLOCK_SIZE;
+}
+
+static int sqlcipher_nss_get_hmac_sz(void *ctx, int algorithm) {
+ switch(algorithm) {
+ case SQLCIPHER_HMAC_SHA1:
+ return SHA1_LENGTH;
+ break;
+ case SQLCIPHER_HMAC_SHA256:
+ return SHA256_LENGTH;
+ break;
+ case SQLCIPHER_HMAC_SHA512:
+ return SHA512_LENGTH;
+ break;
+ default:
+ return 0;
+ }
+}
+
+static int sqlcipher_nss_hmac(void *ctx, int algorithm, unsigned char *hmac_key, int key_sz, unsigned char *in, int in_sz, unsigned char *in2, int in2_sz, unsigned char *out) {
+ int rc = SQLITE_OK;
+ unsigned int length;
+ unsigned int outLen;
+ PK11Context* context = NULL;
+ PK11SlotInfo * slot = NULL;
+ PK11SymKey* symKey = NULL;
+ if(in == NULL) goto error;
+ CK_MECHANISM_TYPE mech;
+ switch(algorithm) {
+ case SQLCIPHER_HMAC_SHA1:
+ mech = CKM_SHA_1_HMAC;
+ break;
+ case SQLCIPHER_HMAC_SHA256:
+ mech = CKM_SHA256_HMAC;
+ break;
+ case SQLCIPHER_HMAC_SHA512:
+ mech = CKM_SHA512_HMAC;
+ break;
+ default:
+ goto error;
+ }
+ length = sqlcipher_nss_get_hmac_sz(ctx, algorithm);
+ slot = PK11_GetInternalSlot();
+ if (slot == NULL) goto error;
+ SECItem keyItem;
+ keyItem.data = hmac_key;
+ keyItem.len = key_sz;
+ symKey = PK11_ImportSymKey(slot, mech, PK11_OriginUnwrap,
+ CKA_SIGN, &keyItem, NULL);
+ if (symKey == NULL) goto error;
+ SECItem noParams;
+ noParams.data = 0;
+ noParams.len = 0;
+ context = PK11_CreateContextBySymKey(mech, CKA_SIGN, symKey, &noParams);
+ if (context == NULL) goto error;
+ if (PK11_DigestBegin(context) != SECSuccess) goto error;
+ if (PK11_DigestOp(context, in, in_sz) != SECSuccess) goto error;
+ if (in2 != NULL) {
+ if (PK11_DigestOp(context, in2, in2_sz) != SECSuccess) goto error;
+ }
+ if (PK11_DigestFinal(context, out, &outLen, length) != SECSuccess) goto error;
+
+ goto cleanup;
+ error:
+ rc = SQLITE_ERROR;
+ cleanup:
+ if (context) PK11_DestroyContext(context, PR_TRUE);
+ if (symKey) PK11_FreeSymKey(symKey);
+ if (slot) PK11_FreeSlot(slot);
+ return rc;
+}
+
+static int sqlcipher_nss_kdf(void *ctx, int algorithm, const unsigned char *pass, int pass_sz, unsigned char* salt, int salt_sz, int workfactor, int key_sz, unsigned char *key) {
+ int rc = SQLITE_OK;
+ PK11SlotInfo * slot = NULL;
+ SECAlgorithmID * algid = NULL;
+ PK11SymKey* symKey = NULL;
+ SECOidTag oidtag;
+ switch(algorithm) {
+ case SQLCIPHER_HMAC_SHA1:
+ oidtag = SEC_OID_HMAC_SHA1;
+ break;
+ case SQLCIPHER_HMAC_SHA256:
+ oidtag = SEC_OID_HMAC_SHA256;
+ break;
+ case SQLCIPHER_HMAC_SHA512:
+ oidtag = SEC_OID_HMAC_SHA512;
+ break;
+ default:
+ goto error;
+ }
+ SECItem secSalt;
+ secSalt.data = salt;
+ secSalt.len = salt_sz;
+ // Always pass SEC_OID_HMAC_SHA1 (i.e. PBMAC1) as this parameter
+ // is unused for key generation. It is currently only used
+ // for PBKDF2 authentication or key (un)wrapping when specifying an
+ // encryption algorithm (PBES2).
+ algid = PK11_CreatePBEV2AlgorithmID(SEC_OID_PKCS5_PBKDF2, SEC_OID_HMAC_SHA1,
+ oidtag, key_sz, workfactor, &secSalt);
+ if (algid == NULL) goto error;
+ slot = PK11_GetInternalSlot();
+ if (slot == NULL) goto error;
+ SECItem pwItem;
+ pwItem.data = (unsigned char *) pass; // PK11_PBEKeyGen doesn't modify the key.
+ pwItem.len = pass_sz;
+ symKey = PK11_PBEKeyGen(slot, algid, &pwItem, PR_FALSE, NULL);
+ if (symKey == NULL) goto error;
+ if (PK11_ExtractKeyValue(symKey) != SECSuccess) goto error;
+ // No need to free keyData as it is a buffer managed by symKey.
+ SECItem* keyData = PK11_GetKeyData(symKey);
+ if (keyData == NULL) goto error;
+ memcpy(key, keyData->data, key_sz);
+
+ goto cleanup;
+ error:
+ rc = SQLITE_ERROR;
+ cleanup:
+ if (slot) PK11_FreeSlot(slot);
+ if (algid) SECOID_DestroyAlgorithmID(algid, PR_TRUE);
+ if (symKey) PK11_FreeSymKey(symKey);
+ return rc;
+}
+
+static int sqlcipher_nss_cipher(void *ctx, int mode, unsigned char *key, int key_sz, unsigned char *iv, unsigned char *in, int in_sz, unsigned char *out) {
+ int rc = SQLITE_OK;
+ PK11SlotInfo * slot = NULL;
+ PK11SymKey* symKey = NULL;
+ unsigned int outLen;
+ SECItem params;
+ params.data = iv;
+ params.len = sqlcipher_nss_get_iv_sz(ctx);
+ slot = PK11_GetInternalSlot();
+ if (slot == NULL) goto error;
+ SECItem keyItem;
+ keyItem.data = key;
+ keyItem.len = key_sz;
+ symKey = PK11_ImportSymKey(slot, CKM_AES_CBC, PK11_OriginUnwrap,
+ CKA_ENCRYPT, &keyItem, NULL);
+ if (symKey == NULL) goto error;
+ SECStatus rv;
+ if (mode == CIPHER_ENCRYPT) {
+ rv = PK11_Encrypt(symKey, CKM_AES_CBC, &params, out, &outLen,
+ in_sz + 16, in, in_sz);
+ } else {
+ rv = PK11_Decrypt(symKey, CKM_AES_CBC, &params, out, &outLen,
+ in_sz + 16, in, in_sz);
+ }
+ if (rv != SECSuccess) goto error;
+
+ goto cleanup;
+ error:
+ rc = SQLITE_ERROR;
+ cleanup:
+ if (slot) PK11_FreeSlot(slot);
+ if (symKey) PK11_FreeSymKey(symKey);
+ return rc;
+}
+
+static int sqlcipher_nss_ctx_init(void **ctx) {
+ sqlcipher_nss_activate(NULL);
+ return SQLITE_OK;
+}
+
+static int sqlcipher_nss_ctx_free(void **ctx) {
+ sqlcipher_nss_deactivate(NULL);
+ return SQLITE_OK;
+}
+
+static int sqlcipher_nss_fips_status(void *ctx) {
+ return 0;
+}
+
+int sqlcipher_nss_setup(sqlcipher_provider *p) {
+ p->activate = sqlcipher_nss_activate;
+ p->deactivate = sqlcipher_nss_deactivate;
+ p->random = sqlcipher_nss_random;
+ p->get_provider_name = sqlcipher_nss_get_provider_name;
+ p->hmac = sqlcipher_nss_hmac;
+ p->kdf = sqlcipher_nss_kdf;
+ p->cipher = sqlcipher_nss_cipher;
+ p->get_cipher = sqlcipher_nss_get_cipher;
+ p->get_key_sz = sqlcipher_nss_get_key_sz;
+ p->get_iv_sz = sqlcipher_nss_get_iv_sz;
+ p->get_block_sz = sqlcipher_nss_get_block_sz;
+ p->get_hmac_sz = sqlcipher_nss_get_hmac_sz;
+ p->ctx_init = sqlcipher_nss_ctx_init;
+ p->ctx_free = sqlcipher_nss_ctx_free;
+ p->add_random = sqlcipher_nss_add_random;
+ p->fips_status = sqlcipher_nss_fips_status;
+ p->get_provider_version = sqlcipher_nss_get_provider_version;
+ return SQLITE_OK;
+}
+
+#endif
+#endif
+/* END SQLCIPHER */
+
+/************** End of crypto_nss.c ******************************************/
+/************** Begin file crypto_openssl.c **********************************/
+/*
+** SQLCipher
+** http://sqlcipher.net
+**
+** Copyright (c) 2008 - 2013, ZETETIC LLC
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** * Neither the name of the ZETETIC LLC nor the
+** names of its contributors may be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY ZETETIC LLC ''AS IS'' AND ANY
+** EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+** DISCLAIMED. IN NO EVENT SHALL ZETETIC LLC BE LIABLE FOR ANY
+** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**
+*/
+/* BEGIN SQLCIPHER */
+#ifdef SQLITE_HAS_CODEC
+#ifdef SQLCIPHER_CRYPTO_OPENSSL
+/* #include "sqliteInt.h" */
+/* #include "crypto.h" */
+/* #include "sqlcipher.h" */
+#include <openssl/crypto.h>
+#include <openssl/rand.h>
+#include <openssl/evp.h>
+#include <openssl/objects.h>
+#include <openssl/hmac.h>
+#include <openssl/err.h>
+
+static unsigned int openssl_init_count = 0;
+
+static void sqlcipher_openssl_log_errors() {
+ unsigned long err = 0;
+ while((err = ERR_get_error()) != 0) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_openssl_log_errors: ERR_get_error() returned %lx: %s", err, ERR_error_string(err, NULL));
+ }
+}
+
+#if (defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x10100000L) || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L)
+static HMAC_CTX *HMAC_CTX_new(void)
+{
+ HMAC_CTX *ctx = OPENSSL_malloc(sizeof(*ctx));
+ if (ctx != NULL) {
+ HMAC_CTX_init(ctx);
+ }
+ return ctx;
+}
+
+/* Per 1.1.0 (https://wiki.openssl.org/index.php/1.1_API_Changes)
+ HMAC_CTX_free should call HMAC_CTX_cleanup, then EVP_MD_CTX_Cleanup.
+ HMAC_CTX_cleanup internally calls EVP_MD_CTX_cleanup so these
+ calls are not needed. */
+static void HMAC_CTX_free(HMAC_CTX *ctx)
+{
+ if (ctx != NULL) {
+ HMAC_CTX_cleanup(ctx);
+ OPENSSL_free(ctx);
+ }
+}
+#endif
+
+static int sqlcipher_openssl_add_random(void *ctx, void *buffer, int length) {
+#ifndef SQLCIPHER_OPENSSL_NO_MUTEX_RAND
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_openssl_add_random: entering SQLCIPHER_MUTEX_PROVIDER_RAND");
+ sqlcipher_sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_RAND));
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_openssl_add_random: entered SQLCIPHER_MUTEX_PROVIDER_RAND");
+#endif
+ RAND_add(buffer, length, 0);
+#ifndef SQLCIPHER_OPENSSL_NO_MUTEX_RAND
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_openssl_add_random: leaving SQLCIPHER_MUTEX_PROVIDER_RAND");
+ sqlcipher_sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_RAND));
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_openssl_add_random: left SQLCIPHER_MUTEX_PROVIDER_RAND");
+#endif
+ return SQLITE_OK;
+}
+
+#define OPENSSL_CIPHER EVP_aes_256_cbc()
+
+/* activate and initialize sqlcipher. Most importantly, this will automatically
+ intialize OpenSSL's EVP system if it hasn't already be externally. Note that
+ this function may be called multiple times as new codecs are intiialized.
+ Thus it performs some basic counting to ensure that only the last and final
+ sqlcipher_openssl_deactivate() will free the EVP structures.
+*/
+static int sqlcipher_openssl_activate(void *ctx) {
+ /* initialize openssl and increment the internal init counter
+ but only if it hasn't been initalized outside of SQLCipher by this program
+ e.g. on startup */
+ int rc = 0;
+
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_openssl_activate: entering SQLCIPHER_MUTEX_PROVIDER_ACTIVATE");
+ sqlcipher_sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE));
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_openssl_activate: entered SQLCIPHER_MUTEX_PROVIDER_ACTIVATE");
+
+#if (defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x10100000L)
+ ERR_load_crypto_strings();
+#endif
+
+#ifdef SQLCIPHER_FIPS
+ if(!FIPS_mode()){
+ if(!(rc = FIPS_mode_set(1))){
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_openssl_activate: FIPS_mode_set() returned %d", rc);
+ sqlcipher_openssl_log_errors();
+ }
+ }
+#endif
+
+ openssl_init_count++;
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_openssl_activate: leaving SQLCIPHER_MUTEX_PROVIDER_ACTIVATE");
+ sqlcipher_sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE));
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_openssl_activate: left SQLCIPHER_MUTEX_PROVIDER_ACTIVATE");
+ return SQLITE_OK;
+}
+
+/* deactivate SQLCipher, most imporantly decremeting the activation count and
+ freeing the EVP structures on the final deactivation to ensure that
+ OpenSSL memory is cleaned up */
+static int sqlcipher_openssl_deactivate(void *ctx) {
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_openssl_deactivate: entering SQLCIPHER_MUTEX_PROVIDER_ACTIVATE");
+ sqlcipher_sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE));
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_openssl_deactivate: entered SQLCIPHER_MUTEX_PROVIDER_ACTIVATE");
+
+ openssl_init_count--;
+
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_openssl_deactivate: leaving SQLCIPHER_MUTEX_PROVIDER_ACTIVATE");
+ sqlcipher_sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE));
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_openssl_deactivate: left SQLCIPHER_MUTEX_PROVIDER_ACTIVATE");
+ return SQLITE_OK;
+}
+
+static const char* sqlcipher_openssl_get_provider_name(void *ctx) {
+ return "openssl";
+}
+
+static const char* sqlcipher_openssl_get_provider_version(void *ctx) {
+ return OPENSSL_VERSION_TEXT;
+}
+
+/* generate a defined number of random bytes */
+static int sqlcipher_openssl_random (void *ctx, void *buffer, int length) {
+ int rc = 0;
+ /* concurrent calls to RAND_bytes can cause a crash under some openssl versions when a
+ naive application doesn't use CRYPTO_set_locking_callback and
+ CRYPTO_THREADID_set_callback to ensure openssl thread safety.
+ This is simple workaround to prevent this common crash
+ but a more proper solution is that applications setup platform-appropriate
+ thread saftey in openssl externally */
+#ifndef SQLCIPHER_OPENSSL_NO_MUTEX_RAND
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_openssl_random: entering SQLCIPHER_MUTEX_PROVIDER_RAND");
+ sqlcipher_sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_RAND));
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_openssl_random: entered SQLCIPHER_MUTEX_PROVIDER_RAND");
+#endif
+ rc = RAND_bytes((unsigned char *)buffer, length);
+#ifndef SQLCIPHER_OPENSSL_NO_MUTEX_RAND
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_openssl_random: leaving SQLCIPHER_MUTEX_PROVIDER_RAND");
+ sqlcipher_sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_RAND));
+ sqlcipher_log(SQLCIPHER_LOG_TRACE, "sqlcipher_openssl_random: left SQLCIPHER_MUTEX_PROVIDER_RAND");
+#endif
+ if(!rc) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_openssl_random: RAND_bytes() returned %d", rc);
+ sqlcipher_openssl_log_errors();
+ return SQLITE_ERROR;
+ }
+ return SQLITE_OK;
+}
+
+static int sqlcipher_openssl_hmac(void *ctx, int algorithm, unsigned char *hmac_key, int key_sz, unsigned char *in, int in_sz, unsigned char *in2, int in2_sz, unsigned char *out) {
+ int rc = 0;
+
+#if (defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x30000000L)
+ unsigned int outlen;
+ HMAC_CTX* hctx = NULL;
+
+ if(in == NULL) goto error;
+
+ hctx = HMAC_CTX_new();
+ if(hctx == NULL) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_openssl_hmac: HMAC_CTX_new() failed");
+ sqlcipher_openssl_log_errors();
+ goto error;
+ }
+
+ switch(algorithm) {
+ case SQLCIPHER_HMAC_SHA1:
+ if(!(rc = HMAC_Init_ex(hctx, hmac_key, key_sz, EVP_sha1(), NULL))) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_openssl_hmac: HMAC_Init_ex() with key size %d and EVP_sha1() returned %d", key_sz, rc);
+ sqlcipher_openssl_log_errors();
+ goto error;
+ }
+ break;
+ case SQLCIPHER_HMAC_SHA256:
+ if(!(rc = HMAC_Init_ex(hctx, hmac_key, key_sz, EVP_sha256(), NULL))) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_openssl_hmac: HMAC_Init_ex() with key size %d and EVP_sha256() returned %d", key_sz, rc);
+ sqlcipher_openssl_log_errors();
+ goto error;
+ }
+ break;
+ case SQLCIPHER_HMAC_SHA512:
+ if(!(rc = HMAC_Init_ex(hctx, hmac_key, key_sz, EVP_sha512(), NULL))) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_openssl_hmac: HMAC_Init_ex() with key size %d and EVP_sha512() returned %d", key_sz, rc);
+ sqlcipher_openssl_log_errors();
+ goto error;
+ }
+ break;
+ default:
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_openssl_hmac: invalid algorithm %d", algorithm);
+ goto error;
+ }
+
+ if(!(rc = HMAC_Update(hctx, in, in_sz))) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_openssl_hmac: HMAC_Update() on 1st input buffer of %d bytes using algorithm %d returned %d", in_sz, algorithm, rc);
+ sqlcipher_openssl_log_errors();
+ goto error;
+ }
+
+ if(in2 != NULL) {
+ if(!(rc = HMAC_Update(hctx, in2, in2_sz))) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_openssl_hmac: HMAC_Update() on 2nd input buffer of %d bytes using algorithm %d returned %d", in2_sz, algorithm, rc);
+ sqlcipher_openssl_log_errors();
+ goto error;
+ }
+ }
+
+ if(!(rc = HMAC_Final(hctx, out, &outlen))) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_openssl_hmac: HMAC_Final() using algorithm %d returned %d", algorithm, rc);
+ sqlcipher_openssl_log_errors();
+ goto error;
+ }
+
+ rc = SQLITE_OK;
+ goto cleanup;
+
+error:
+ rc = SQLITE_ERROR;
+
+cleanup:
+ if(hctx) HMAC_CTX_free(hctx);
+
+#else
+ size_t outlen;
+ EVP_MAC *mac = NULL;
+ EVP_MAC_CTX *hctx = NULL;
+ OSSL_PARAM sha1[] = { { "digest", OSSL_PARAM_UTF8_STRING, "sha1", 4, 0 }, OSSL_PARAM_END };
+ OSSL_PARAM sha256[] = { { "digest", OSSL_PARAM_UTF8_STRING, "sha256", 6, 0 }, OSSL_PARAM_END };
+ OSSL_PARAM sha512[] = { { "digest", OSSL_PARAM_UTF8_STRING, "sha512", 6, 0 }, OSSL_PARAM_END };
+
+ if(in == NULL) goto error;
+
+ mac = EVP_MAC_fetch(NULL, "HMAC", NULL);
+ if(mac == NULL) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_openssl_hmac: EVP_MAC_fetch for HMAC failed");
+ sqlcipher_openssl_log_errors();
+ goto error;
+ }
+
+ hctx = EVP_MAC_CTX_new(mac);
+ if(hctx == NULL) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_openssl_hmac: EVP_MAC_CTX_new() failed");
+ sqlcipher_openssl_log_errors();
+ goto error;
+ }
+
+ switch(algorithm) {
+ case SQLCIPHER_HMAC_SHA1:
+ if(!(rc = EVP_MAC_init(hctx, hmac_key, key_sz, sha1))) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_openssl_hmac: EVP_MAC_init() with key size %d and sha1 returned %d", key_sz, rc);
+ sqlcipher_openssl_log_errors();
+ goto error;
+ }
+ break;
+ case SQLCIPHER_HMAC_SHA256:
+ if(!(rc = EVP_MAC_init(hctx, hmac_key, key_sz, sha256))) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_openssl_hmac: EVP_MAC_init() with key size %d and sha256 returned %d", key_sz, rc);
+ sqlcipher_openssl_log_errors();
+ goto error;
+ }
+ break;
+ case SQLCIPHER_HMAC_SHA512:
+ if(!(rc = EVP_MAC_init(hctx, hmac_key, key_sz, sha512))) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_openssl_hmac: EVP_MAC_init() with key size %d and sha512 returned %d", key_sz, rc);
+ sqlcipher_openssl_log_errors();
+ goto error;
+ }
+ break;
+ default:
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_openssl_hmac: invalid algorithm %d", algorithm);
+ goto error;
+ }
+
+ if(!(rc = EVP_MAC_update(hctx, in, in_sz))) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_openssl_hmac: EVP_MAC_update() on 1st input buffer of %d bytes using algorithm %d returned %d", in_sz, algorithm, rc);
+ sqlcipher_openssl_log_errors();
+ goto error;
+ }
+
+ if(in2 != NULL) {
+ if(!(rc = EVP_MAC_update(hctx, in2, in2_sz))) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_openssl_hmac: EVP_MAC_update() on 2nd input buffer of %d bytes using algorithm %d returned %d", in_sz, algorithm, rc);
+ sqlcipher_openssl_log_errors();
+ goto error;
+ }
+ }
+
+ if(!(rc = EVP_MAC_final(hctx, NULL, &outlen, 0))) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_openssl_hmac: 1st EVP_MAC_final() for output length calculation using algorithm %d returned %d", algorithm, rc);
+ sqlcipher_openssl_log_errors();
+ goto error;
+ }
+
+ if(!(rc = EVP_MAC_final(hctx, out, &outlen, outlen))) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_openssl_hmac: 2nd EVP_MAC_final() using algorithm %d returned %d", algorithm, rc);
+ sqlcipher_openssl_log_errors();
+ goto error;
+ }
+
+ rc = SQLITE_OK;
+ goto cleanup;
+
+error:
+ rc = SQLITE_ERROR;
+
+cleanup:
+ if(hctx) EVP_MAC_CTX_free(hctx);
+ if(mac) EVP_MAC_free(mac);
+
+#endif
+
+ return rc;
+}
+
+static int sqlcipher_openssl_kdf(void *ctx, int algorithm, const unsigned char *pass, int pass_sz, unsigned char* salt, int salt_sz, int workfactor, int key_sz, unsigned char *key) {
+ int rc = 0;
+
+ switch(algorithm) {
+ case SQLCIPHER_HMAC_SHA1:
+ if(!(rc = PKCS5_PBKDF2_HMAC((const char *)pass, pass_sz, salt, salt_sz, workfactor, EVP_sha1(), key_sz, key))) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_openssl_kdf: PKCS5_PBKDF2_HMAC() for EVP_sha1() workfactor %d and key size %d returned %d", workfactor, key_sz, rc);
+ sqlcipher_openssl_log_errors();
+ goto error;
+ }
+ break;
+ case SQLCIPHER_HMAC_SHA256:
+ if(!(rc = PKCS5_PBKDF2_HMAC((const char *)pass, pass_sz, salt, salt_sz, workfactor, EVP_sha256(), key_sz, key))) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_openssl_kdf: PKCS5_PBKDF2_HMAC() for EVP_sha256() workfactor %d and key size %d returned %d", workfactor, key_sz, rc);
+ sqlcipher_openssl_log_errors();
+ goto error;
+ }
+ break;
+ case SQLCIPHER_HMAC_SHA512:
+ if(!(rc = PKCS5_PBKDF2_HMAC((const char *)pass, pass_sz, salt, salt_sz, workfactor, EVP_sha512(), key_sz, key))) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_openssl_kdf: PKCS5_PBKDF2_HMAC() for EVP_sha512() workfactor %d and key size %d returned %d", workfactor, key_sz, rc);
+ sqlcipher_openssl_log_errors();
+ goto error;
+ }
+ break;
+ default:
+ return SQLITE_ERROR;
+ }
+
+ rc = SQLITE_OK;
+ goto cleanup;
+error:
+ rc = SQLITE_ERROR;
+cleanup:
+ return rc;
+}
+
+static int sqlcipher_openssl_cipher(void *ctx, int mode, unsigned char *key, int key_sz, unsigned char *iv, unsigned char *in, int in_sz, unsigned char *out) {
+ int tmp_csz, csz, rc = 0;
+ EVP_CIPHER_CTX* ectx = EVP_CIPHER_CTX_new();
+ if(ectx == NULL) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_openssl_cipher: EVP_CIPHER_CTX_new failed");
+ sqlcipher_openssl_log_errors();
+ goto error;
+ }
+
+ if(!(rc = EVP_CipherInit_ex(ectx, OPENSSL_CIPHER, NULL, NULL, NULL, mode))) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_openssl_cipher: EVP_CipherInit_ex for mode %d returned %d", mode, rc);
+ sqlcipher_openssl_log_errors();
+ goto error;
+ }
+
+ if(!(rc = EVP_CIPHER_CTX_set_padding(ectx, 0))) { /* no padding */
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_openssl_cipher: EVP_CIPHER_CTX_set_padding 0 returned %d", rc);
+ sqlcipher_openssl_log_errors();
+ goto error;
+ }
+
+ if(!(rc = EVP_CipherInit_ex(ectx, NULL, NULL, key, iv, mode))) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_openssl_cipher: EVP_CipherInit_ex for mode %d returned %d", mode, rc);
+ sqlcipher_openssl_log_errors();
+ goto error;
+ }
+
+ if(!(rc = EVP_CipherUpdate(ectx, out, &tmp_csz, in, in_sz))) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_openssl_cipher: EVP_CipherUpdate returned %d", rc);
+ sqlcipher_openssl_log_errors();
+ goto error;
+ }
+
+ csz = tmp_csz;
+ out += tmp_csz;
+ if(!(rc = EVP_CipherFinal_ex(ectx, out, &tmp_csz))) {
+ sqlcipher_log(SQLCIPHER_LOG_ERROR, "sqlcipher_openssl_cipher: EVP_CipherFinal_ex returned %d", rc);
+ sqlcipher_openssl_log_errors();
+ goto error;
+ }
+
+ csz += tmp_csz;
+ assert(in_sz == csz);
+
+ rc = SQLITE_OK;
+ goto cleanup;
+error:
+ rc = SQLITE_ERROR;
+cleanup:
+ if(ectx) EVP_CIPHER_CTX_free(ectx);
+ return rc;
+}
+
+static const char* sqlcipher_openssl_get_cipher(void *ctx) {
+ return OBJ_nid2sn(EVP_CIPHER_nid(OPENSSL_CIPHER));
+}
+
+static int sqlcipher_openssl_get_key_sz(void *ctx) {
+ return EVP_CIPHER_key_length(OPENSSL_CIPHER);
+}
+
+static int sqlcipher_openssl_get_iv_sz(void *ctx) {
+ return EVP_CIPHER_iv_length(OPENSSL_CIPHER);
+}
+
+static int sqlcipher_openssl_get_block_sz(void *ctx) {
+ return EVP_CIPHER_block_size(OPENSSL_CIPHER);
+}
+
+static int sqlcipher_openssl_get_hmac_sz(void *ctx, int algorithm) {
+ switch(algorithm) {
+ case SQLCIPHER_HMAC_SHA1:
+ return EVP_MD_size(EVP_sha1());
+ break;
+ case SQLCIPHER_HMAC_SHA256:
+ return EVP_MD_size(EVP_sha256());
+ break;
+ case SQLCIPHER_HMAC_SHA512:
+ return EVP_MD_size(EVP_sha512());
+ break;
+ default:
+ return 0;
+ }
+}
+
+static int sqlcipher_openssl_ctx_init(void **ctx) {
+ return sqlcipher_openssl_activate(*ctx);
+}
+
+static int sqlcipher_openssl_ctx_free(void **ctx) {
+ return sqlcipher_openssl_deactivate(NULL);
+}
+
+static int sqlcipher_openssl_fips_status(void *ctx) {
+#ifdef SQLCIPHER_FIPS
+ return FIPS_mode();
+#else
+ return 0;
+#endif
+}
+
+int sqlcipher_openssl_setup(sqlcipher_provider *p) {
+ p->activate = sqlcipher_openssl_activate;
+ p->deactivate = sqlcipher_openssl_deactivate;
+ p->get_provider_name = sqlcipher_openssl_get_provider_name;
+ p->random = sqlcipher_openssl_random;
+ p->hmac = sqlcipher_openssl_hmac;
+ p->kdf = sqlcipher_openssl_kdf;
+ p->cipher = sqlcipher_openssl_cipher;
+ p->get_cipher = sqlcipher_openssl_get_cipher;
+ p->get_key_sz = sqlcipher_openssl_get_key_sz;
+ p->get_iv_sz = sqlcipher_openssl_get_iv_sz;
+ p->get_block_sz = sqlcipher_openssl_get_block_sz;
+ p->get_hmac_sz = sqlcipher_openssl_get_hmac_sz;
+ p->ctx_init = sqlcipher_openssl_ctx_init;
+ p->ctx_free = sqlcipher_openssl_ctx_free;
+ p->add_random = sqlcipher_openssl_add_random;
+ p->fips_status = sqlcipher_openssl_fips_status;
+ p->get_provider_version = sqlcipher_openssl_get_provider_version;
+ return SQLITE_OK;
+}
+
+#endif
+#endif
+/* END SQLCIPHER */
+
+/************** End of crypto_openssl.c **************************************/
+/************** Begin file crypto_cc.c ***************************************/
+/*
+** SQLCipher
+** http://sqlcipher.net
+**
+** Copyright (c) 2008 - 2013, ZETETIC LLC
+** All rights reserved.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** * Neither the name of the ZETETIC LLC nor the
+** names of its contributors may be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY ZETETIC LLC ''AS IS'' AND ANY
+** EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+** DISCLAIMED. IN NO EVENT SHALL ZETETIC LLC BE LIABLE FOR ANY
+** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**
+*/
+/* BEGIN SQLCIPHER */
+#ifdef SQLITE_HAS_CODEC
+#ifdef SQLCIPHER_CRYPTO_CC
+/* #include "crypto.h" */
+/* #include "sqlcipher.h" */
+#include <CommonCrypto/CommonCrypto.h>
+#include <Security/SecRandom.h>
+#include <CoreFoundation/CoreFoundation.h>
+
+int sqlcipher_cc_setup(sqlcipher_provider *p);
+
+static int sqlcipher_cc_add_random(void *ctx, void *buffer, int length) {
+ return SQLITE_OK;
+}
+
+/* generate a defined number of random bytes */
+static int sqlcipher_cc_random (void *ctx, void *buffer, int length) {
+ return (SecRandomCopyBytes(kSecRandomDefault, length, (uint8_t *)buffer) == kCCSuccess) ? SQLITE_OK : SQLITE_ERROR;
+}
+
+static const char* sqlcipher_cc_get_provider_name(void *ctx) {
+ return "commoncrypto";
+}
+
+static const char* sqlcipher_cc_get_provider_version(void *ctx) {
+#if TARGET_OS_MAC
+ CFTypeRef version;
+ CFBundleRef bundle = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.security"));
+ if(bundle == NULL) {
+ return "unknown";
+ }
+ version = CFBundleGetValueForInfoDictionaryKey(bundle, CFSTR("CFBundleShortVersionString"));
+ return CFStringGetCStringPtr(version, kCFStringEncodingUTF8);
+#else
+ return "unknown";
+#endif
+}
+
+static int sqlcipher_cc_hmac(void *ctx, int algorithm, unsigned char *hmac_key, int key_sz, unsigned char *in, int in_sz, unsigned char *in2, int in2_sz, unsigned char *out) {
+ CCHmacContext hmac_context;
+ if(in == NULL) return SQLITE_ERROR;
+ switch(algorithm) {
+ case SQLCIPHER_HMAC_SHA1:
+ CCHmacInit(&hmac_context, kCCHmacAlgSHA1, hmac_key, key_sz);
+ break;
+ case SQLCIPHER_HMAC_SHA256:
+ CCHmacInit(&hmac_context, kCCHmacAlgSHA256, hmac_key, key_sz);
+ break;
+ case SQLCIPHER_HMAC_SHA512:
+ CCHmacInit(&hmac_context, kCCHmacAlgSHA512, hmac_key, key_sz);
+ break;
+ default:
+ return SQLITE_ERROR;
+ }
+ CCHmacUpdate(&hmac_context, in, in_sz);
+ if(in2 != NULL) CCHmacUpdate(&hmac_context, in2, in2_sz);
+ CCHmacFinal(&hmac_context, out);
+ return SQLITE_OK;
+}
+
+static int sqlcipher_cc_kdf(void *ctx, int algorithm, const unsigned char *pass, int pass_sz, unsigned char* salt, int salt_sz, int workfactor, int key_sz, unsigned char *key) {
+ switch(algorithm) {
+ case SQLCIPHER_HMAC_SHA1:
+ if(CCKeyDerivationPBKDF(kCCPBKDF2, (const char *)pass, pass_sz, salt, salt_sz, kCCPRFHmacAlgSHA1, workfactor, key, key_sz) != kCCSuccess) return SQLITE_ERROR;
+ break;
+ case SQLCIPHER_HMAC_SHA256:
+ if(CCKeyDerivationPBKDF(kCCPBKDF2, (const char *)pass, pass_sz, salt, salt_sz, kCCPRFHmacAlgSHA256, workfactor, key, key_sz) != kCCSuccess) return SQLITE_ERROR;
+ break;
+ case SQLCIPHER_HMAC_SHA512:
+ if(CCKeyDerivationPBKDF(kCCPBKDF2, (const char *)pass, pass_sz, salt, salt_sz, kCCPRFHmacAlgSHA512, workfactor, key, key_sz) != kCCSuccess) return SQLITE_ERROR;
+ break;
+ default:
+ return SQLITE_ERROR;
+ }
+ return SQLITE_OK;
+}
+
+static int sqlcipher_cc_cipher(void *ctx, int mode, unsigned char *key, int key_sz, unsigned char *iv, unsigned char *in, int in_sz, unsigned char *out) {
+ CCCryptorRef cryptor;
+ size_t tmp_csz, csz;
+ CCOperation op = mode == CIPHER_ENCRYPT ? kCCEncrypt : kCCDecrypt;
+
+ if(CCCryptorCreate(op, kCCAlgorithmAES128, 0, key, kCCKeySizeAES256, iv, &cryptor) != kCCSuccess) return SQLITE_ERROR;
+ if(CCCryptorUpdate(cryptor, in, in_sz, out, in_sz, &tmp_csz) != kCCSuccess) return SQLITE_ERROR;
+ csz = tmp_csz;
+ out += tmp_csz;
+ if(CCCryptorFinal(cryptor, out, in_sz - csz, &tmp_csz) != kCCSuccess) return SQLITE_ERROR;
+ csz += tmp_csz;
+ if(CCCryptorRelease(cryptor) != kCCSuccess) return SQLITE_ERROR;
+ assert(in_sz == csz);
+
+ return SQLITE_OK;
+}
+
+static const char* sqlcipher_cc_get_cipher(void *ctx) {
+ return "aes-256-cbc";
+}
+
+static int sqlcipher_cc_get_key_sz(void *ctx) {
+ return kCCKeySizeAES256;
+}
+
+static int sqlcipher_cc_get_iv_sz(void *ctx) {
+ return kCCBlockSizeAES128;
+}
+
+static int sqlcipher_cc_get_block_sz(void *ctx) {
+ return kCCBlockSizeAES128;
+}
+
+static int sqlcipher_cc_get_hmac_sz(void *ctx, int algorithm) {
+ switch(algorithm) {
+ case SQLCIPHER_HMAC_SHA1:
+ return CC_SHA1_DIGEST_LENGTH;
+ break;
+ case SQLCIPHER_HMAC_SHA256:
+ return CC_SHA256_DIGEST_LENGTH;
+ break;
+ case SQLCIPHER_HMAC_SHA512:
+ return CC_SHA512_DIGEST_LENGTH;
+ break;
+ default:
+ return 0;
+ }
+}
+
+static int sqlcipher_cc_ctx_init(void **ctx) {
+ return SQLITE_OK;
+}
+
+static int sqlcipher_cc_ctx_free(void **ctx) {
+ return SQLITE_OK;
+}
+
+static int sqlcipher_cc_fips_status(void *ctx) {
+ return 0;
+}
+
+int sqlcipher_cc_setup(sqlcipher_provider *p) {
+ p->random = sqlcipher_cc_random;
+ p->get_provider_name = sqlcipher_cc_get_provider_name;
+ p->hmac = sqlcipher_cc_hmac;
+ p->kdf = sqlcipher_cc_kdf;
+ p->cipher = sqlcipher_cc_cipher;
+ p->get_cipher = sqlcipher_cc_get_cipher;
+ p->get_key_sz = sqlcipher_cc_get_key_sz;
+ p->get_iv_sz = sqlcipher_cc_get_iv_sz;
+ p->get_block_sz = sqlcipher_cc_get_block_sz;
+ p->get_hmac_sz = sqlcipher_cc_get_hmac_sz;
+ p->ctx_init = sqlcipher_cc_ctx_init;
+ p->ctx_free = sqlcipher_cc_ctx_free;
+ p->add_random = sqlcipher_cc_add_random;
+ p->fips_status = sqlcipher_cc_fips_status;
+ p->get_provider_version = sqlcipher_cc_get_provider_version;
+ return SQLITE_OK;
+}
+
+#endif
+#endif
+/* END SQLCIPHER */
+
+/************** End of crypto_cc.c *******************************************/
/************** Begin file walker.c ******************************************/
/*
** 2008 August 16
@@ -102691,7 +106475,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3JournalSize(sqlcipher_sqlite3_vfs *pVfs){
** Walk all expressions linked into the list of Window objects passed
** as the second argument.
*/
-static int walkWindowList(Walker *pWalker, Window *pList){
+static int walkWindowList(Walker *pWalker, Window *pList, int bOneOnly){
Window *pWin;
for(pWin=pList; pWin; pWin=pWin->pNextWin){
int rc;
@@ -102701,15 +106485,11 @@ static int walkWindowList(Walker *pWalker, Window *pList){
if( rc ) return WRC_Abort;
rc = sqlcipher_sqlite3WalkExpr(pWalker, pWin->pFilter);
if( rc ) return WRC_Abort;
-
- /* The next two are purely for calls to sqlcipher_sqlite3RenameExprUnmap()
- ** within sqlcipher_sqlite3WindowOffsetExpr(). Because of constraints imposed
- ** by sqlcipher_sqlite3WindowOffsetExpr(), they can never fail. The results do
- ** not matter anyhow. */
rc = sqlcipher_sqlite3WalkExpr(pWalker, pWin->pStart);
- if( NEVER(rc) ) return WRC_Abort;
+ if( rc ) return WRC_Abort;
rc = sqlcipher_sqlite3WalkExpr(pWalker, pWin->pEnd);
- if( NEVER(rc) ) return WRC_Abort;
+ if( rc ) return WRC_Abort;
+ if( bOneOnly ) break;
}
return WRC_Continue;
}
@@ -102748,7 +106528,7 @@ static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){
assert( !ExprHasProperty(pExpr, EP_WinFunc) );
pExpr = pExpr->pRight;
continue;
- }else if( ExprHasProperty(pExpr, EP_xIsSelect) ){
+ }else if( ExprUseXSelect(pExpr) ){
assert( !ExprHasProperty(pExpr, EP_WinFunc) );
if( sqlcipher_sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort;
}else{
@@ -102757,7 +106537,7 @@ static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){
}
#ifndef SQLITE_OMIT_WINDOWFUNC
if( ExprHasProperty(pExpr, EP_WinFunc) ){
- if( walkWindowList(pWalker, pExpr->y.pWin) ) return WRC_Abort;
+ if( walkWindowList(pWalker, pExpr->y.pWin, 1) ) return WRC_Abort;
}
#endif
}
@@ -102786,6 +106566,16 @@ SQLITE_PRIVATE int sqlcipher_sqlite3WalkExprList(Walker *pWalker, ExprList *p){
}
/*
+** This is a no-op callback for Walker->xSelectCallback2. If this
+** callback is set, then the Select->pWinDefn list is traversed.
+*/
+SQLITE_PRIVATE void sqlcipher_sqlite3WalkWinDefnDummyCallback(Walker *pWalker, Select *p){
+ UNUSED_PARAMETER(pWalker);
+ UNUSED_PARAMETER(p);
+ /* No-op */
+}
+
+/*
** Walk all expressions associated with SELECT statement p. Do
** not invoke the SELECT callback on p, but do (of course) invoke
** any expr callbacks and SELECT callbacks that come from subqueries.
@@ -102798,13 +106588,18 @@ SQLITE_PRIVATE int sqlcipher_sqlite3WalkSelectExpr(Walker *pWalker, Select *p){
if( sqlcipher_sqlite3WalkExpr(pWalker, p->pHaving) ) return WRC_Abort;
if( sqlcipher_sqlite3WalkExprList(pWalker, p->pOrderBy) ) return WRC_Abort;
if( sqlcipher_sqlite3WalkExpr(pWalker, p->pLimit) ) return WRC_Abort;
-#if !defined(SQLITE_OMIT_WINDOWFUNC) && !defined(SQLITE_OMIT_ALTERTABLE)
- {
- Parse *pParse = pWalker->pParse;
- if( pParse && IN_RENAME_OBJECT ){
+#if !defined(SQLITE_OMIT_WINDOWFUNC)
+ if( p->pWinDefn ){
+ Parse *pParse;
+ if( pWalker->xSelectCallback2==sqlcipher_sqlite3WalkWinDefnDummyCallback
+ || ((pParse = pWalker->pParse)!=0 && IN_RENAME_OBJECT)
+#ifndef SQLITE_OMIT_CTE
+ || pWalker->xSelectCallback2==sqlcipher_sqlite3SelectPopWith
+#endif
+ ){
/* The following may return WRC_Abort if there are unresolvable
** symbols (e.g. a table that does not exist) in a window definition. */
- int rc = walkWindowList(pWalker, p->pWinDefn);
+ int rc = walkWindowList(pWalker, p->pWinDefn, 0);
return rc;
}
}
@@ -102822,10 +106617,10 @@ SQLITE_PRIVATE int sqlcipher_sqlite3WalkSelectExpr(Walker *pWalker, Select *p){
SQLITE_PRIVATE int sqlcipher_sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
SrcList *pSrc;
int i;
- struct SrcList_item *pItem;
+ SrcItem *pItem;
pSrc = p->pSrc;
- if( pSrc ){
+ if( ALWAYS(pSrc) ){
for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
if( pItem->pSelect && sqlcipher_sqlite3WalkSelect(pWalker, pItem->pSelect) ){
return WRC_Abort;
@@ -102988,7 +106783,6 @@ static void resolveAlias(
ExprList *pEList, /* A result set */
int iCol, /* A column in the result set. 0..pEList->nExpr-1 */
Expr *pExpr, /* Transform this into an alias to the result set */
- const char *zType, /* "GROUP" or "ORDER" or "" */
int nSubquery /* Number of subqueries that the label is moving */
){
Expr *pOrig; /* The iCol-th column of the result set */
@@ -103000,54 +106794,28 @@ static void resolveAlias(
assert( pOrig!=0 );
db = pParse->db;
pDup = sqlcipher_sqlite3ExprDup(db, pOrig, 0);
- if( pDup!=0 ){
- if( zType[0]!='G' ) incrAggFunctionDepth(pDup, nSubquery);
+ if( db->mallocFailed ){
+ sqlcipher_sqlite3ExprDelete(db, pDup);
+ pDup = 0;
+ }else{
+ Expr temp;
+ incrAggFunctionDepth(pDup, nSubquery);
if( pExpr->op==TK_COLLATE ){
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
pDup = sqlcipher_sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken);
}
-
- /* Before calling sqlcipher_sqlite3ExprDelete(), set the EP_Static flag. This
- ** prevents ExprDelete() from deleting the Expr structure itself,
- ** allowing it to be repopulated by the memcpy() on the following line.
- ** The pExpr->u.zToken might point into memory that will be freed by the
- ** sqlcipher_sqlite3DbFree(db, pDup) on the last line of this block, so be sure to
- ** make a copy of the token before doing the sqlcipher_sqlite3DbFree().
- */
- ExprSetProperty(pExpr, EP_Static);
- sqlcipher_sqlite3ExprDelete(db, pExpr);
- memcpy(pExpr, pDup, sizeof(*pExpr));
- if( !ExprHasProperty(pExpr, EP_IntValue) && pExpr->u.zToken!=0 ){
- assert( (pExpr->flags & (EP_Reduced|EP_TokenOnly))==0 );
- pExpr->u.zToken = sqlcipher_sqlite3DbStrDup(db, pExpr->u.zToken);
- pExpr->flags |= EP_MemToken;
- }
+ memcpy(&temp, pDup, sizeof(Expr));
+ memcpy(pDup, pExpr, sizeof(Expr));
+ memcpy(pExpr, &temp, sizeof(Expr));
if( ExprHasProperty(pExpr, EP_WinFunc) ){
- if( pExpr->y.pWin!=0 ){
+ if( ALWAYS(pExpr->y.pWin!=0) ){
pExpr->y.pWin->pOwner = pExpr;
- }else{
- assert( db->mallocFailed );
}
}
- sqlcipher_sqlite3DbFree(db, pDup);
- }
- ExprSetProperty(pExpr, EP_Alias);
-}
-
-
-/*
-** Return TRUE if the name zCol occurs anywhere in the USING clause.
-**
-** Return FALSE if the USING clause is NULL or if it does not contain
-** zCol.
-*/
-static int nameInUsingClause(IdList *pUsing, const char *zCol){
- if( pUsing ){
- int k;
- for(k=0; k<pUsing->nId; k++){
- if( sqlcipher_sqlite3StrICmp(pUsing->a[k].zName, zCol)==0 ) return 1;
- }
+ sqlcipher_sqlite3ParserAddCleanup(pParse,
+ (void(*)(sqlcipher_sqlite3*,void*))sqlcipher_sqlite3ExprDelete,
+ pDup);
}
- return 0;
}
/*
@@ -103065,7 +106833,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3MatchEName(
){
int n;
const char *zSpan;
- if( pItem->eEName!=ENAME_TAB ) return 0;
+ if( pItem->fg.eEName!=ENAME_TAB ) return 0;
zSpan = pItem->zEName;
for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){}
if( zDb && (sqlcipher_sqlite3StrNICmp(zSpan, zDb, n)!=0 || zDb[n]!=0) ){
@@ -103109,6 +106877,7 @@ SQLITE_PRIVATE Bitmask sqlcipher_sqlite3ExprColUsed(Expr *pExpr){
Table *pExTab;
n = pExpr->iColumn;
+ assert( ExprUseYTab(pExpr) );
pExTab = pExpr->y.pTab;
assert( pExTab!=0 );
if( (pExTab->tabFlags & TF_HasGenerated)!=0
@@ -103126,6 +106895,29 @@ SQLITE_PRIVATE Bitmask sqlcipher_sqlite3ExprColUsed(Expr *pExpr){
}
/*
+** Create a new expression term for the column specified by pMatch and
+** iColumn. Append this new expression term to the FULL JOIN Match set
+** in *ppList. Create a new *ppList if this is the first term in the
+** set.
+*/
+static void extendFJMatch(
+ Parse *pParse, /* Parsing context */
+ ExprList **ppList, /* ExprList to extend */
+ SrcItem *pMatch, /* Source table containing the column */
+ i16 iColumn /* The column number */
+){
+ Expr *pNew = sqlcipher_sqlite3ExprAlloc(pParse->db, TK_COLUMN, 0, 0);
+ if( pNew ){
+ pNew->iTable = pMatch->iCursor;
+ pNew->iColumn = iColumn;
+ pNew->y.pTab = pMatch->pTab;
+ assert( (pMatch->fg.jointype & (JT_LEFT|JT_LTORJ))!=0 );
+ ExprSetProperty(pNew, EP_CanBeNull);
+ *ppList = sqlcipher_sqlite3ExprListAppend(pParse, *ppList, pNew);
+ }
+}
+
+/*
** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up
** that name in the set of source tables in pSrcList and make the pExpr
** expression node refer back to that source column. The following changes
@@ -103165,16 +106957,18 @@ static int lookupName(
int cntTab = 0; /* Number of matching table names */
int nSubquery = 0; /* How many levels of subquery */
sqlcipher_sqlite3 *db = pParse->db; /* The database connection */
- struct SrcList_item *pItem; /* Use for looping over pSrcList items */
- struct SrcList_item *pMatch = 0; /* The matching pSrcList item */
+ SrcItem *pItem; /* Use for looping over pSrcList items */
+ SrcItem *pMatch = 0; /* The matching pSrcList item */
NameContext *pTopNC = pNC; /* First namecontext in the list */
Schema *pSchema = 0; /* Schema of the expression */
int eNewExprOp = TK_COLUMN; /* New value for pExpr->op on success */
- Table *pTab = 0; /* Table hold the row */
+ Table *pTab = 0; /* Table holding the row */
Column *pCol; /* A column of pTab */
+ ExprList *pFJMatch = 0; /* Matches for FULL JOIN .. USING */
assert( pNC ); /* the name context cannot be NULL. */
assert( zCol ); /* The Z in X.Y.Z cannot be NULL */
+ assert( zDb==0 || zTab!=0 );
assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) );
/* Initialize the node to no-match */
@@ -103222,62 +107016,124 @@ static int lookupName(
u8 hCol;
pTab = pItem->pTab;
assert( pTab!=0 && pTab->zName!=0 );
- assert( pTab->nCol>0 );
- if( pItem->pSelect && (pItem->pSelect->selFlags & SF_NestedFrom)!=0 ){
+ assert( pTab->nCol>0 || pParse->nErr );
+ assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem->pSelect) );
+ if( pItem->fg.isNestedFrom ){
+ /* In this case, pItem is a subquery that has been formed from a
+ ** parenthesized subset of the FROM clause terms. Example:
+ ** .... FROM t1 LEFT JOIN (t2 RIGHT JOIN t3 USING(x)) USING(y) ...
+ ** \_________________________/
+ ** This pItem -------------^
+ */
int hit = 0;
+ assert( pItem->pSelect!=0 );
pEList = pItem->pSelect->pEList;
+ assert( pEList!=0 );
+ assert( pEList->nExpr==pTab->nCol );
for(j=0; j<pEList->nExpr; j++){
- if( sqlcipher_sqlite3MatchEName(&pEList->a[j], zCol, zTab, zDb) ){
- cnt++;
- cntTab = 2;
- pMatch = pItem;
- pExpr->iColumn = j;
- hit = 1;
+ if( !sqlcipher_sqlite3MatchEName(&pEList->a[j], zCol, zTab, zDb) ){
+ continue;
+ }
+ if( cnt>0 ){
+ if( pItem->fg.isUsing==0
+ || sqlcipher_sqlite3IdListIndex(pItem->u3.pUsing, zCol)<0
+ ){
+ /* Two or more tables have the same column name which is
+ ** not joined by USING. This is an error. Signal as much
+ ** by clearing pFJMatch and letting cnt go above 1. */
+ sqlcipher_sqlite3ExprListDelete(db, pFJMatch);
+ pFJMatch = 0;
+ }else
+ if( (pItem->fg.jointype & JT_RIGHT)==0 ){
+ /* An INNER or LEFT JOIN. Use the left-most table */
+ continue;
+ }else
+ if( (pItem->fg.jointype & JT_LEFT)==0 ){
+ /* A RIGHT JOIN. Use the right-most table */
+ cnt = 0;
+ sqlcipher_sqlite3ExprListDelete(db, pFJMatch);
+ pFJMatch = 0;
+ }else{
+ /* For a FULL JOIN, we must construct a coalesce() func */
+ extendFJMatch(pParse, &pFJMatch, pMatch, pExpr->iColumn);
+ }
}
+ cnt++;
+ cntTab = 2;
+ pMatch = pItem;
+ pExpr->iColumn = j;
+ pEList->a[j].fg.bUsed = 1;
+ hit = 1;
+ if( pEList->a[j].fg.bUsingTerm ) break;
}
if( hit || zTab==0 ) continue;
}
- if( zDb && pTab->pSchema!=pSchema ){
- continue;
- }
+ assert( zDb==0 || zTab!=0 );
if( zTab ){
- const char *zTabName = pItem->zAlias ? pItem->zAlias : pTab->zName;
+ const char *zTabName;
+ if( zDb ){
+ if( pTab->pSchema!=pSchema ) continue;
+ if( pSchema==0 && strcmp(zDb,"*")!=0 ) continue;
+ }
+ zTabName = pItem->zAlias ? pItem->zAlias : pTab->zName;
assert( zTabName!=0 );
if( sqlcipher_sqlite3StrICmp(zTabName, zTab)!=0 ){
continue;
}
+ assert( ExprUseYTab(pExpr) );
if( IN_RENAME_OBJECT && pItem->zAlias ){
sqlcipher_sqlite3RenameTokenRemap(pParse, 0, (void*)&pExpr->y.pTab);
}
}
- if( 0==(cntTab++) ){
- pMatch = pItem;
- }
hCol = sqlcipher_sqlite3StrIHash(zCol);
for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
- if( pCol->hName==hCol && sqlcipher_sqlite3StrICmp(pCol->zName, zCol)==0 ){
- /* If there has been exactly one prior match and this match
- ** is for the right-hand table of a NATURAL JOIN or is in a
- ** USING clause, then skip this match.
- */
- if( cnt==1 ){
- if( pItem->fg.jointype & JT_NATURAL ) continue;
- if( nameInUsingClause(pItem->pUsing, zCol) ) continue;
+ if( pCol->hName==hCol
+ && sqlcipher_sqlite3StrICmp(pCol->zCnName, zCol)==0
+ ){
+ if( cnt>0 ){
+ if( pItem->fg.isUsing==0
+ || sqlcipher_sqlite3IdListIndex(pItem->u3.pUsing, zCol)<0
+ ){
+ /* Two or more tables have the same column name which is
+ ** not joined by USING. This is an error. Signal as much
+ ** by clearing pFJMatch and letting cnt go above 1. */
+ sqlcipher_sqlite3ExprListDelete(db, pFJMatch);
+ pFJMatch = 0;
+ }else
+ if( (pItem->fg.jointype & JT_RIGHT)==0 ){
+ /* An INNER or LEFT JOIN. Use the left-most table */
+ continue;
+ }else
+ if( (pItem->fg.jointype & JT_LEFT)==0 ){
+ /* A RIGHT JOIN. Use the right-most table */
+ cnt = 0;
+ sqlcipher_sqlite3ExprListDelete(db, pFJMatch);
+ pFJMatch = 0;
+ }else{
+ /* For a FULL JOIN, we must construct a coalesce() func */
+ extendFJMatch(pParse, &pFJMatch, pMatch, pExpr->iColumn);
+ }
}
cnt++;
pMatch = pItem;
/* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
pExpr->iColumn = j==pTab->iPKey ? -1 : (i16)j;
+ if( pItem->fg.isNestedFrom ){
+ sqlcipher_sqlite3SrcItemColumnUsed(pItem, j);
+ }
break;
}
}
+ if( 0==cnt && VisibleRowid(pTab) ){
+ cntTab++;
+ pMatch = pItem;
+ }
}
if( pMatch ){
pExpr->iTable = pMatch->iCursor;
+ assert( ExprUseYTab(pExpr) );
pExpr->y.pTab = pMatch->pTab;
- /* RIGHT JOIN not (yet) supported */
- assert( (pMatch->fg.jointype & JT_RIGHT)==0 );
- if( (pMatch->fg.jointype & JT_LEFT)!=0 ){
+ if( (pMatch->fg.jointype & (JT_LEFT|JT_LTORJ))!=0 ){
ExprSetProperty(pExpr, EP_CanBeNull);
}
pSchema = pExpr->y.pTab->pSchema;
@@ -103287,25 +107143,33 @@ static int lookupName(
#if !defined(SQLITE_OMIT_TRIGGER) || !defined(SQLITE_OMIT_UPSERT)
/* If we have not already resolved the name, then maybe
** it is a new.* or old.* trigger argument reference. Or
- ** maybe it is an excluded.* from an upsert.
+ ** maybe it is an excluded.* from an upsert. Or maybe it is
+ ** a reference in the RETURNING clause to a table being modified.
*/
- if( zDb==0 && zTab!=0 && cntTab==0 ){
+ if( cnt==0 && zDb==0 ){
pTab = 0;
#ifndef SQLITE_OMIT_TRIGGER
if( pParse->pTriggerTab!=0 ){
int op = pParse->eTriggerOp;
assert( op==TK_DELETE || op==TK_UPDATE || op==TK_INSERT );
- if( op!=TK_DELETE && sqlcipher_sqlite3StrICmp("new",zTab) == 0 ){
+ if( pParse->bReturning ){
+ if( (pNC->ncFlags & NC_UBaseReg)!=0
+ && (zTab==0 || sqlcipher_sqlite3StrICmp(zTab,pParse->pTriggerTab->zName)==0)
+ ){
+ pExpr->iTable = op!=TK_DELETE;
+ pTab = pParse->pTriggerTab;
+ }
+ }else if( op!=TK_DELETE && zTab && sqlcipher_sqlite3StrICmp("new",zTab) == 0 ){
pExpr->iTable = 1;
pTab = pParse->pTriggerTab;
- }else if( op!=TK_INSERT && sqlcipher_sqlite3StrICmp("old",zTab)==0 ){
+ }else if( op!=TK_INSERT && zTab && sqlcipher_sqlite3StrICmp("old",zTab)==0 ){
pExpr->iTable = 0;
pTab = pParse->pTriggerTab;
}
}
#endif /* SQLITE_OMIT_TRIGGER */
#ifndef SQLITE_OMIT_UPSERT
- if( (pNC->ncFlags & NC_UUpsert)!=0 ){
+ if( (pNC->ncFlags & NC_UUpsert)!=0 && zTab!=0 ){
Upsert *pUpsert = pNC->uNC.pUpsert;
if( pUpsert && sqlcipher_sqlite3StrICmp("excluded",zTab)==0 ){
pTab = pUpsert->pUpsertSrc->a[0].pTab;
@@ -103320,7 +107184,9 @@ static int lookupName(
pSchema = pTab->pSchema;
cntTab++;
for(iCol=0, pCol=pTab->aCol; iCol<pTab->nCol; iCol++, pCol++){
- if( pCol->hName==hCol && sqlcipher_sqlite3StrICmp(pCol->zName, zCol)==0 ){
+ if( pCol->hName==hCol
+ && sqlcipher_sqlite3StrICmp(pCol->zCnName, zCol)==0
+ ){
if( iCol==pTab->iPKey ){
iCol = -1;
}
@@ -103333,9 +107199,11 @@ static int lookupName(
}
if( iCol<pTab->nCol ){
cnt++;
+ pMatch = 0;
#ifndef SQLITE_OMIT_UPSERT
if( pExpr->iTable==EXCLUDED_TABLE_NUMBER ){
testcase( iCol==(-1) );
+ assert( ExprUseYTab(pExpr) );
if( IN_RENAME_OBJECT ){
pExpr->iColumn = iCol;
pExpr->y.pTab = pTab;
@@ -103344,27 +107212,34 @@ static int lookupName(
pExpr->iTable = pNC->uNC.pUpsert->regData +
sqlcipher_sqlite3TableColumnToStorage(pTab, iCol);
eNewExprOp = TK_REGISTER;
- ExprSetProperty(pExpr, EP_Alias);
}
}else
#endif /* SQLITE_OMIT_UPSERT */
{
-#ifndef SQLITE_OMIT_TRIGGER
- if( iCol<0 ){
- pExpr->affExpr = SQLITE_AFF_INTEGER;
- }else if( pExpr->iTable==0 ){
- testcase( iCol==31 );
- testcase( iCol==32 );
- pParse->oldmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol));
- }else{
- testcase( iCol==31 );
- testcase( iCol==32 );
- pParse->newmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol));
- }
+ assert( ExprUseYTab(pExpr) );
pExpr->y.pTab = pTab;
- pExpr->iColumn = (i16)iCol;
- eNewExprOp = TK_TRIGGER;
+ if( pParse->bReturning ){
+ eNewExprOp = TK_REGISTER;
+ pExpr->op2 = TK_COLUMN;
+ pExpr->iTable = pNC->uNC.iBaseReg + (pTab->nCol+1)*pExpr->iTable +
+ sqlcipher_sqlite3TableColumnToStorage(pTab, iCol) + 1;
+ }else{
+ pExpr->iColumn = (i16)iCol;
+ eNewExprOp = TK_TRIGGER;
+#ifndef SQLITE_OMIT_TRIGGER
+ if( iCol<0 ){
+ pExpr->affExpr = SQLITE_AFF_INTEGER;
+ }else if( pExpr->iTable==0 ){
+ testcase( iCol==31 );
+ testcase( iCol==32 );
+ pParse->oldmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol));
+ }else{
+ testcase( iCol==31 );
+ testcase( iCol==32 );
+ pParse->newmask |= (iCol>=32 ? 0xffffffff : (((u32)1)<<iCol));
+ }
#endif /* SQLITE_OMIT_TRIGGER */
+ }
}
}
}
@@ -103379,7 +107254,7 @@ static int lookupName(
&& pMatch
&& (pNC->ncFlags & (NC_IdxExpr|NC_GenCol))==0
&& sqlcipher_sqlite3IsRowid(zCol)
- && VisibleRowid(pMatch->pTab)
+ && ALWAYS(VisibleRowid(pMatch->pTab))
){
cnt = 1;
pExpr->iColumn = -1;
@@ -103404,21 +107279,21 @@ static int lookupName(
** is supported for backwards compatibility only. Hence, we issue a warning
** on sqlcipher_sqlite3_log() whenever the capability is used.
*/
- if( (pNC->ncFlags & NC_UEList)!=0
- && cnt==0
+ if( cnt==0
+ && (pNC->ncFlags & NC_UEList)!=0
&& zTab==0
){
pEList = pNC->uNC.pEList;
assert( pEList!=0 );
for(j=0; j<pEList->nExpr; j++){
char *zAs = pEList->a[j].zEName;
- if( pEList->a[j].eEName==ENAME_NAME
+ if( pEList->a[j].fg.eEName==ENAME_NAME
&& sqlcipher_sqlite3_stricmp(zAs, zCol)==0
){
Expr *pOrig;
assert( pExpr->pLeft==0 && pExpr->pRight==0 );
- assert( pExpr->x.pList==0 );
- assert( pExpr->x.pSelect==0 );
+ assert( ExprUseXList(pExpr)==0 || pExpr->x.pList==0 );
+ assert( ExprUseXSelect(pExpr)==0 || pExpr->x.pSelect==0 );
pOrig = pEList->a[j].pExpr;
if( (pNC->ncFlags&NC_AllowAgg)==0 && ExprHasProperty(pOrig, EP_Agg) ){
sqlcipher_sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs);
@@ -103434,7 +107309,7 @@ static int lookupName(
sqlcipher_sqlite3ErrorMsg(pParse, "row value misused");
return WRC_Abort;
}
- resolveAlias(pParse, pEList, j, pExpr, "", nSubquery);
+ resolveAlias(pParse, pEList, j, pExpr, nSubquery);
cnt = 1;
pMatch = 0;
assert( zTab==0 && zDb==0 );
@@ -103490,7 +107365,7 @@ static int lookupName(
sqlcipher_sqlite3VdbeAddDblquoteStr(db, pParse->pVdbe, zCol);
#endif
pExpr->op = TK_STRING;
- pExpr->y.pTab = 0;
+ memset(&pExpr->y, 0, sizeof(pExpr->y));
return WRC_Prune;
}
if( sqlcipher_sqlite3ExprIdToTrueFalse(pExpr) ){
@@ -103499,11 +107374,37 @@ static int lookupName(
}
/*
- ** cnt==0 means there was not match. cnt>1 means there were two or
- ** more matches. Either way, we have an error.
+ ** cnt==0 means there was not match.
+ ** cnt>1 means there were two or more matches.
+ **
+ ** cnt==0 is always an error. cnt>1 is often an error, but might
+ ** be multiple matches for a NATURAL LEFT JOIN or a LEFT JOIN USING.
*/
+ assert( pFJMatch==0 || cnt>0 );
+ assert( !ExprHasProperty(pExpr, EP_xIsSelect|EP_IntValue) );
if( cnt!=1 ){
const char *zErr;
+ if( pFJMatch ){
+ if( pFJMatch->nExpr==cnt-1 ){
+ if( ExprHasProperty(pExpr,EP_Leaf) ){
+ ExprClearProperty(pExpr,EP_Leaf);
+ }else{
+ sqlcipher_sqlite3ExprDelete(db, pExpr->pLeft);
+ pExpr->pLeft = 0;
+ sqlcipher_sqlite3ExprDelete(db, pExpr->pRight);
+ pExpr->pRight = 0;
+ }
+ extendFJMatch(pParse, &pFJMatch, pMatch, pExpr->iColumn);
+ pExpr->op = TK_FUNCTION;
+ pExpr->u.zToken = "coalesce";
+ pExpr->x.pList = pFJMatch;
+ cnt = 1;
+ goto lookupname_end;
+ }else{
+ sqlcipher_sqlite3ExprListDelete(db, pFJMatch);
+ pFJMatch = 0;
+ }
+ }
zErr = cnt==0 ? "no such column" : "ambiguous column name";
if( zDb ){
sqlcipher_sqlite3ErrorMsg(pParse, "%s: %s.%s.%s", zErr, zDb, zTab, zCol);
@@ -103512,8 +107413,19 @@ static int lookupName(
}else{
sqlcipher_sqlite3ErrorMsg(pParse, "%s: %s", zErr, zCol);
}
+ sqlcipher_sqlite3RecordErrorOffsetOfExpr(pParse->db, pExpr);
pParse->checkSchema = 1;
- pTopNC->nErr++;
+ pTopNC->nNcErr++;
+ }
+ assert( pFJMatch==0 );
+
+ /* Remove all substructure from pExpr */
+ if( !ExprHasProperty(pExpr,(EP_TokenOnly|EP_Leaf)) ){
+ sqlcipher_sqlite3ExprDelete(db, pExpr->pLeft);
+ pExpr->pLeft = 0;
+ sqlcipher_sqlite3ExprDelete(db, pExpr->pRight);
+ pExpr->pRight = 0;
+ ExprSetProperty(pExpr, EP_Leaf);
}
/* If a column from a table in pSrcList is referenced, then record
@@ -103534,20 +107446,17 @@ static int lookupName(
pMatch->colUsed |= sqlcipher_sqlite3ExprColUsed(pExpr);
}
- /* Clean up and return
- */
- sqlcipher_sqlite3ExprDelete(db, pExpr->pLeft);
- pExpr->pLeft = 0;
- sqlcipher_sqlite3ExprDelete(db, pExpr->pRight);
- pExpr->pRight = 0;
pExpr->op = eNewExprOp;
- ExprSetProperty(pExpr, EP_Leaf);
lookupname_end:
if( cnt==1 ){
assert( pNC!=0 );
- if( !ExprHasProperty(pExpr, EP_Alias) ){
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ if( pParse->db->xAuth
+ && (pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER)
+ ){
sqlcipher_sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList);
}
+#endif
/* Increment the nRef value on all name contexts from TopNC up to
** the point where the name matched. */
for(;;){
@@ -103569,8 +107478,10 @@ lookupname_end:
SQLITE_PRIVATE Expr *sqlcipher_sqlite3CreateColumnExpr(sqlcipher_sqlite3 *db, SrcList *pSrc, int iSrc, int iCol){
Expr *p = sqlcipher_sqlite3ExprAlloc(db, TK_COLUMN, 0, 0);
if( p ){
- struct SrcList_item *pItem = &pSrc->a[iSrc];
- Table *pTab = p->y.pTab = pItem->pTab;
+ SrcItem *pItem = &pSrc->a[iSrc];
+ Table *pTab;
+ assert( ExprUseYTab(p) );
+ pTab = p->y.pTab = pItem->pTab;
p->iTable = pItem->iCursor;
if( p->y.pTab->iPKey==iCol ){
p->iColumn = -1;
@@ -103612,7 +107523,8 @@ static void notValidImpl(
Parse *pParse, /* Leave error message here */
NameContext *pNC, /* The name context */
const char *zMsg, /* Type of error */
- Expr *pExpr /* Invalidate this expression on error */
+ Expr *pExpr, /* Invalidate this expression on error */
+ Expr *pError /* Associate error with this expression */
){
const char *zIn = "partial index WHERE clauses";
if( pNC->ncFlags & NC_IdxExpr ) zIn = "index expressions";
@@ -103624,10 +107536,11 @@ static void notValidImpl(
#endif
sqlcipher_sqlite3ErrorMsg(pParse, "%s prohibited in %s", zMsg, zIn);
if( pExpr ) pExpr->op = TK_NULL;
+ sqlcipher_sqlite3RecordErrorOffsetOfExpr(pParse->db, pError);
}
-#define sqlcipher_sqlite3ResolveNotValid(P,N,M,X,E) \
+#define sqlcipher_sqlite3ResolveNotValid(P,N,M,X,E,R) \
assert( ((X)&~(NC_IsCheck|NC_PartIdx|NC_IdxExpr|NC_GenCol))==0 ); \
- if( ((N)->ncFlags & (X))!=0 ) notValidImpl(P,N,M,E);
+ if( ((N)->ncFlags & (X))!=0 ) notValidImpl(P,N,M,E,R);
/*
** Expression p should encode a floating point value between 1.0 and 0.0.
@@ -103637,6 +107550,7 @@ static void notValidImpl(
static int exprProbability(Expr *p){
double r = -1.0;
if( p->op!=TK_FLOAT ) return -1;
+ assert( !ExprHasProperty(p, EP_IntValue) );
sqlcipher_sqlite3AtoF(p->u.zToken, &r, sqlcipher_sqlite3Strlen30(p->u.zToken), SQLITE_UTF8);
assert( r>=0.0 );
if( r>1.0 ) return -1;
@@ -103681,10 +107595,11 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
*/
case TK_ROW: {
SrcList *pSrcList = pNC->pSrcList;
- struct SrcList_item *pItem;
+ SrcItem *pItem;
assert( pSrcList && pSrcList->nSrc>=1 );
pItem = pSrcList->a;
pExpr->op = TK_COLUMN;
+ assert( ExprUseYTab(pExpr) );
pExpr->y.pTab = pItem->pTab;
pExpr->iTable = pItem->iCursor;
pExpr->iColumn--;
@@ -103692,6 +107607,49 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
break;
}
+ /* An optimization: Attempt to convert
+ **
+ ** "expr IS NOT NULL" --> "TRUE"
+ ** "expr IS NULL" --> "FALSE"
+ **
+ ** if we can prove that "expr" is never NULL. Call this the
+ ** "NOT NULL strength reduction optimization".
+ **
+ ** If this optimization occurs, also restore the NameContext ref-counts
+ ** to the state they where in before the "column" LHS expression was
+ ** resolved. This prevents "column" from being counted as having been
+ ** referenced, which might prevent a SELECT from being erroneously
+ ** marked as correlated.
+ */
+ case TK_NOTNULL:
+ case TK_ISNULL: {
+ int anRef[8];
+ NameContext *p;
+ int i;
+ for(i=0, p=pNC; p && i<ArraySize(anRef); p=p->pNext, i++){
+ anRef[i] = p->nRef;
+ }
+ sqlcipher_sqlite3WalkExpr(pWalker, pExpr->pLeft);
+ if( 0==sqlcipher_sqlite3ExprCanBeNull(pExpr->pLeft) && !IN_RENAME_OBJECT ){
+ testcase( ExprHasProperty(pExpr, EP_OuterON) );
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
+ if( pExpr->op==TK_NOTNULL ){
+ pExpr->u.zToken = "true";
+ ExprSetProperty(pExpr, EP_IsTrue);
+ }else{
+ pExpr->u.zToken = "false";
+ ExprSetProperty(pExpr, EP_IsFalse);
+ }
+ pExpr->op = TK_TRUEFALSE;
+ for(i=0, p=pNC; p && i<ArraySize(anRef); p=p->pNext, i++){
+ p->nRef = anRef[i];
+ }
+ sqlcipher_sqlite3ExprDelete(pParse->db, pExpr->pLeft);
+ pExpr->pLeft = 0;
+ }
+ return WRC_Prune;
+ }
+
/* A column name: ID
** Or table name and column name: ID.ID
** Or a database, table and column: ID.ID.ID
@@ -103710,24 +107668,28 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
if( pExpr->op==TK_ID ){
zDb = 0;
zTable = 0;
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
zColumn = pExpr->u.zToken;
}else{
Expr *pLeft = pExpr->pLeft;
testcase( pNC->ncFlags & NC_IdxExpr );
testcase( pNC->ncFlags & NC_GenCol );
sqlcipher_sqlite3ResolveNotValid(pParse, pNC, "the \".\" operator",
- NC_IdxExpr|NC_GenCol, 0);
+ NC_IdxExpr|NC_GenCol, 0, pExpr);
pRight = pExpr->pRight;
if( pRight->op==TK_ID ){
zDb = 0;
}else{
assert( pRight->op==TK_DOT );
+ assert( !ExprHasProperty(pRight, EP_IntValue) );
zDb = pLeft->u.zToken;
pLeft = pRight->pLeft;
pRight = pRight->pRight;
}
+ assert( ExprUseUToken(pLeft) && ExprUseUToken(pRight) );
zTable = pLeft->u.zToken;
zColumn = pRight->u.zToken;
+ assert( ExprUseYTab(pExpr) );
if( IN_RENAME_OBJECT ){
sqlcipher_sqlite3RenameTokenRemap(pParse, (void*)pExpr, (void*)pRight);
sqlcipher_sqlite3RenameTokenRemap(pParse, (void*)&pExpr->y.pTab, (void*)pLeft);
@@ -103744,7 +107706,6 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
int no_such_func = 0; /* True if no such function exists */
int wrong_num_args = 0; /* True if wrong number of arguments */
int is_agg = 0; /* True if is an aggregate function */
- int nId; /* Number of characters in function name */
const char *zId; /* The function name. */
FuncDef *pDef; /* Information about the function */
u8 enc = ENC(pParse->db); /* The database encoding */
@@ -103752,9 +107713,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
#ifndef SQLITE_OMIT_WINDOWFUNC
Window *pWin = (IsWindowFunc(pExpr) ? pExpr->y.pWin : 0);
#endif
- assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
+ assert( !ExprHasProperty(pExpr, EP_xIsSelect|EP_IntValue) );
zId = pExpr->u.zToken;
- nId = sqlcipher_sqlite3Strlen30(zId);
pDef = sqlcipher_sqlite3FindFunction(pParse->db, zId, n, enc, 0);
if( pDef==0 ){
pDef = sqlcipher_sqlite3FindFunction(pParse->db, zId, -2, enc, 0);
@@ -103771,9 +107731,9 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
pExpr->iTable = exprProbability(pList->a[1].pExpr);
if( pExpr->iTable<0 ){
sqlcipher_sqlite3ErrorMsg(pParse,
- "second argument to likelihood() must be a "
- "constant between 0.0 and 1.0");
- pNC->nErr++;
+ "second argument to %#T() must be a "
+ "constant between 0.0 and 1.0", pExpr);
+ pNC->nNcErr++;
}
}else{
/* EVIDENCE-OF: R-61304-29449 The unlikely(X) function is
@@ -103793,9 +107753,9 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
int auth = sqlcipher_sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0,pDef->zName,0);
if( auth!=SQLITE_OK ){
if( auth==SQLITE_DENY ){
- sqlcipher_sqlite3ErrorMsg(pParse, "not authorized to use function: %s",
- pDef->zName);
- pNC->nErr++;
+ sqlcipher_sqlite3ErrorMsg(pParse, "not authorized to use function: %#T",
+ pExpr);
+ pNC->nNcErr++;
}
pExpr->op = TK_NULL;
return WRC_Prune;
@@ -103817,7 +107777,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
** in a CHECK constraint. SQLServer, MySQL, and PostgreSQL all
** all this. */
sqlcipher_sqlite3ResolveNotValid(pParse, pNC, "non-deterministic functions",
- NC_IdxExpr|NC_PartIdx|NC_GenCol, 0);
+ NC_IdxExpr|NC_PartIdx|NC_GenCol, 0, pExpr);
}else{
assert( (NC_SelfRef & 0xff)==NC_SelfRef ); /* Must fit in 8 bits */
pExpr->op2 = pNC->ncFlags & NC_SelfRef;
@@ -103830,7 +107790,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
/* Internal-use-only functions are disallowed unless the
** SQL is being compiled using sqlcipher_sqlite3NestedParse() or
** the SQLITE_TESTCTRL_INTERNAL_FUNCTIONS test-control has be
- ** used to activate internal functionsn for testing purposes */
+ ** used to activate internal functions for testing purposes */
no_such_func = 1;
pDef = 0;
}else
@@ -103849,9 +107809,9 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
);
if( pDef && pDef->xValue==0 && pWin ){
sqlcipher_sqlite3ErrorMsg(pParse,
- "%.*s() may not be used as a window function", nId, zId
+ "%#T() may not be used as a window function", pExpr
);
- pNC->nErr++;
+ pNC->nNcErr++;
}else if(
(is_agg && (pNC->ncFlags & NC_AllowAgg)==0)
|| (is_agg && (pDef->funcFlags&SQLITE_FUNC_WINDOW) && !pWin)
@@ -103863,14 +107823,14 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
}else{
zType = "aggregate";
}
- sqlcipher_sqlite3ErrorMsg(pParse, "misuse of %s function %.*s()",zType,nId,zId);
- pNC->nErr++;
+ sqlcipher_sqlite3ErrorMsg(pParse, "misuse of %s function %#T()",zType,pExpr);
+ pNC->nNcErr++;
is_agg = 0;
}
#else
if( (is_agg && (pNC->ncFlags & NC_AllowAgg)==0) ){
- sqlcipher_sqlite3ErrorMsg(pParse,"misuse of aggregate function %.*s()",nId,zId);
- pNC->nErr++;
+ sqlcipher_sqlite3ErrorMsg(pParse,"misuse of aggregate function %#T()",pExpr);
+ pNC->nNcErr++;
is_agg = 0;
}
#endif
@@ -103879,20 +107839,20 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
&& pParse->explain==0
#endif
){
- sqlcipher_sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId);
- pNC->nErr++;
+ sqlcipher_sqlite3ErrorMsg(pParse, "no such function: %#T", pExpr);
+ pNC->nNcErr++;
}else if( wrong_num_args ){
- sqlcipher_sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()",
- nId, zId);
- pNC->nErr++;
+ sqlcipher_sqlite3ErrorMsg(pParse,"wrong number of arguments to function %#T()",
+ pExpr);
+ pNC->nNcErr++;
}
#ifndef SQLITE_OMIT_WINDOWFUNC
else if( is_agg==0 && ExprHasProperty(pExpr, EP_WinFunc) ){
sqlcipher_sqlite3ErrorMsg(pParse,
- "FILTER may not be used with non-aggregate %.*s()",
- nId, zId
+ "FILTER may not be used with non-aggregate %#T()",
+ pExpr
);
- pNC->nErr++;
+ pNC->nNcErr++;
}
#endif
if( is_agg ){
@@ -103916,9 +107876,10 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
#ifndef SQLITE_OMIT_WINDOWFUNC
if( pWin ){
Select *pSel = pNC->pWinSelect;
- assert( pWin==pExpr->y.pWin );
+ assert( pWin==0 || (ExprUseYWin(pExpr) && pWin==pExpr->y.pWin) );
if( IN_RENAME_OBJECT==0 ){
sqlcipher_sqlite3WindowUpdate(pParse, pSel ? pSel->pWinDefn : 0, pWin, pDef);
+ if( pParse->db->mallocFailed ) break;
}
sqlcipher_sqlite3WalkExprList(pWalker, pWin->pPartition);
sqlcipher_sqlite3WalkExprList(pWalker, pWin->pOrderBy);
@@ -103928,7 +107889,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
}else
#endif /* SQLITE_OMIT_WINDOWFUNC */
{
- NameContext *pNC2 = pNC;
+ NameContext *pNC2; /* For looping up thru outer contexts */
pExpr->op = TK_AGG_FUNCTION;
pExpr->op2 = 0;
#ifndef SQLITE_OMIT_WINDOWFUNC
@@ -103936,16 +107897,22 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
sqlcipher_sqlite3WalkExpr(pWalker, pExpr->y.pWin->pFilter);
}
#endif
- while( pNC2 && !sqlcipher_sqlite3FunctionUsesThisSrc(pExpr, pNC2->pSrcList) ){
+ pNC2 = pNC;
+ while( pNC2
+ && sqlcipher_sqlite3ReferencesSrcList(pParse, pExpr, pNC2->pSrcList)==0
+ ){
pExpr->op2++;
pNC2 = pNC2->pNext;
}
assert( pDef!=0 || IN_RENAME_OBJECT );
if( pNC2 && pDef ){
assert( SQLITE_FUNC_MINMAX==NC_MinMaxAgg );
+ assert( SQLITE_FUNC_ANYORDER==NC_OrderAgg );
testcase( (pDef->funcFlags & SQLITE_FUNC_MINMAX)!=0 );
- pNC2->ncFlags |= NC_HasAgg | (pDef->funcFlags & SQLITE_FUNC_MINMAX);
-
+ testcase( (pDef->funcFlags & SQLITE_FUNC_ANYORDER)!=0 );
+ pNC2->ncFlags |= NC_HasAgg
+ | ((pDef->funcFlags^SQLITE_FUNC_ANYORDER)
+ & (SQLITE_FUNC_MINMAX|SQLITE_FUNC_ANYORDER));
}
}
pNC->ncFlags |= savedAllowFlags;
@@ -103961,15 +107928,17 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
#endif
case TK_IN: {
testcase( pExpr->op==TK_IN );
- if( ExprHasProperty(pExpr, EP_xIsSelect) ){
+ if( ExprUseXSelect(pExpr) ){
int nRef = pNC->nRef;
testcase( pNC->ncFlags & NC_IsCheck );
testcase( pNC->ncFlags & NC_PartIdx );
testcase( pNC->ncFlags & NC_IdxExpr );
testcase( pNC->ncFlags & NC_GenCol );
- sqlcipher_sqlite3ResolveNotValid(pParse, pNC, "subqueries",
- NC_IsCheck|NC_PartIdx|NC_IdxExpr|NC_GenCol, pExpr);
- sqlcipher_sqlite3WalkSelect(pWalker, pExpr->x.pSelect);
+ if( pNC->ncFlags & NC_SelfRef ){
+ notValidImpl(pParse, pNC, "subqueries", pExpr, pExpr);
+ }else{
+ sqlcipher_sqlite3WalkSelect(pWalker, pExpr->x.pSelect);
+ }
assert( pNC->nRef>=nRef );
if( nRef!=pNC->nRef ){
ExprSetProperty(pExpr, EP_VarSelect);
@@ -103984,7 +107953,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
testcase( pNC->ncFlags & NC_IdxExpr );
testcase( pNC->ncFlags & NC_GenCol );
sqlcipher_sqlite3ResolveNotValid(pParse, pNC, "parameters",
- NC_IsCheck|NC_PartIdx|NC_IdxExpr|NC_GenCol, pExpr);
+ NC_IsCheck|NC_PartIdx|NC_IdxExpr|NC_GenCol, pExpr, pExpr);
break;
}
case TK_IS:
@@ -103993,7 +107962,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
assert( !ExprHasProperty(pExpr, EP_Reduced) );
/* Handle special cases of "x IS TRUE", "x IS FALSE", "x IS NOT TRUE",
** and "x IS NOT FALSE". */
- if( pRight && (pRight->op==TK_ID || pRight->op==TK_TRUEFALSE) ){
+ if( ALWAYS(pRight) && (pRight->op==TK_ID || pRight->op==TK_TRUEFALSE) ){
int rc = resolveExprStep(pWalker, pRight);
if( rc==WRC_Abort ) return WRC_Abort;
if( pRight->op==TK_TRUEFALSE ){
@@ -104016,6 +107985,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
assert( pExpr->pLeft!=0 );
nLeft = sqlcipher_sqlite3ExprVectorSize(pExpr->pLeft);
if( pExpr->op==TK_BETWEEN ){
+ assert( ExprUseXList(pExpr) );
nRight = sqlcipher_sqlite3ExprVectorSize(pExpr->x.pList->a[0].pExpr);
if( nRight==nLeft ){
nRight = sqlcipher_sqlite3ExprVectorSize(pExpr->x.pList->a[1].pExpr);
@@ -104035,11 +108005,13 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
testcase( pExpr->op==TK_ISNOT );
testcase( pExpr->op==TK_BETWEEN );
sqlcipher_sqlite3ErrorMsg(pParse, "row value misused");
+ sqlcipher_sqlite3RecordErrorOffsetOfExpr(pParse->db, pExpr);
}
break;
}
}
- return (pParse->nErr || pParse->db->mallocFailed) ? WRC_Abort : WRC_Continue;
+ assert( pParse->db->mallocFailed==0 || pParse->nErr!=0 );
+ return pParse->nErr ? WRC_Abort : WRC_Continue;
}
/*
@@ -104064,9 +108036,11 @@ static int resolveAsName(
UNUSED_PARAMETER(pParse);
if( pE->op==TK_ID ){
- char *zCol = pE->u.zToken;
+ const char *zCol;
+ assert( !ExprHasProperty(pE, EP_IntValue) );
+ zCol = pE->u.zToken;
for(i=0; i<pEList->nExpr; i++){
- if( pEList->a[i].eEName==ENAME_NAME
+ if( pEList->a[i].fg.eEName==ENAME_NAME
&& sqlcipher_sqlite3_stricmp(pEList->a[i].zEName, zCol)==0
){
return i+1;
@@ -104115,11 +108089,11 @@ static int resolveOrderByTermToExprList(
nc.pParse = pParse;
nc.pSrcList = pSelect->pSrc;
nc.uNC.pEList = pEList;
- nc.ncFlags = NC_AllowAgg|NC_UEList;
- nc.nErr = 0;
+ nc.ncFlags = NC_AllowAgg|NC_UEList|NC_NoSelect;
+ nc.nNcErr = 0;
db = pParse->db;
savedSuppErr = db->suppressErr;
- if( IN_RENAME_OBJECT==0 ) db->suppressErr = 1;
+ db->suppressErr = 1;
rc = sqlcipher_sqlite3ResolveExprNames(&nc, pE);
db->suppressErr = savedSuppErr;
if( rc ) return 0;
@@ -104145,11 +108119,13 @@ static void resolveOutOfRangeError(
Parse *pParse, /* The error context into which to write the error */
const char *zType, /* "ORDER" or "GROUP" */
int i, /* The index (1-based) of the term out of range */
- int mx /* Largest permissible value of i */
+ int mx, /* Largest permissible value of i */
+ Expr *pError /* Associate the error with the expression */
){
sqlcipher_sqlite3ErrorMsg(pParse,
"%r %s BY term out of range - should be "
"between 1 and %d", i, zType, mx);
+ sqlcipher_sqlite3RecordErrorOffsetOfExpr(pParse->db, pError);
}
/*
@@ -104185,7 +108161,7 @@ static int resolveCompoundOrderBy(
return 1;
}
for(i=0; i<pOrderBy->nExpr; i++){
- pOrderBy->a[i].done = 0;
+ pOrderBy->a[i].fg.done = 0;
}
pSelect->pNext = 0;
while( pSelect->pPrior ){
@@ -104200,12 +108176,12 @@ static int resolveCompoundOrderBy(
for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
int iCol = -1;
Expr *pE, *pDup;
- if( pItem->done ) continue;
+ if( pItem->fg.done ) continue;
pE = sqlcipher_sqlite3ExprSkipCollateAndLikely(pItem->pExpr);
if( NEVER(pE==0) ) continue;
if( sqlcipher_sqlite3ExprIsInteger(pE, &iCol) ){
if( iCol<=0 || iCol>pEList->nExpr ){
- resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr);
+ resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr, pE);
return 1;
}
}else{
@@ -104218,29 +108194,24 @@ static int resolveCompoundOrderBy(
** Once the comparisons are finished, the duplicate expression
** is deleted.
**
- ** Or, if this is running as part of an ALTER TABLE operation,
- ** resolve the symbols in the actual expression, not a duplicate.
- ** And, if one of the comparisons is successful, leave the expression
- ** as is instead of transforming it to an integer as in the usual
- ** case. This allows the code in alter.c to modify column
- ** refererences within the ORDER BY expression as required. */
- if( IN_RENAME_OBJECT ){
- pDup = pE;
- }else{
- pDup = sqlcipher_sqlite3ExprDup(db, pE, 0);
- }
+ ** If this is running as part of an ALTER TABLE operation and
+ ** the symbols resolve successfully, also resolve the symbols in the
+ ** actual expression. This allows the code in alter.c to modify
+ ** column references within the ORDER BY expression as required. */
+ pDup = sqlcipher_sqlite3ExprDup(db, pE, 0);
if( !db->mallocFailed ){
assert(pDup);
iCol = resolveOrderByTermToExprList(pParse, pSelect, pDup);
+ if( IN_RENAME_OBJECT && iCol>0 ){
+ resolveOrderByTermToExprList(pParse, pSelect, pE);
+ }
}
- if( !IN_RENAME_OBJECT ){
- sqlcipher_sqlite3ExprDelete(db, pDup);
- }
+ sqlcipher_sqlite3ExprDelete(db, pDup);
}
}
if( iCol>0 ){
/* Convert the ORDER BY term into an integer column number iCol,
- ** taking care to preserve the COLLATE clause if it exists */
+ ** taking care to preserve the COLLATE clause if it exists. */
if( !IN_RENAME_OBJECT ){
Expr *pNew = sqlcipher_sqlite3Expr(db, TK_INTEGER, 0);
if( pNew==0 ) return 1;
@@ -104258,7 +108229,7 @@ static int resolveCompoundOrderBy(
sqlcipher_sqlite3ExprDelete(db, pE);
pItem->u.x.iOrderByCol = (u16)iCol;
}
- pItem->done = 1;
+ pItem->fg.done = 1;
}else{
moreToDo = 1;
}
@@ -104266,7 +108237,7 @@ static int resolveCompoundOrderBy(
pSelect = pSelect->pNext;
}
for(i=0; i<pOrderBy->nExpr; i++){
- if( pOrderBy->a[i].done==0 ){
+ if( pOrderBy->a[i].fg.done==0 ){
sqlcipher_sqlite3ErrorMsg(pParse, "%r ORDER BY term does not match any "
"column in the result set", i+1);
return 1;
@@ -104306,11 +108277,10 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ResolveOrderGroupBy(
for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
if( pItem->u.x.iOrderByCol ){
if( pItem->u.x.iOrderByCol>pEList->nExpr ){
- resolveOutOfRangeError(pParse, zType, i+1, pEList->nExpr);
+ resolveOutOfRangeError(pParse, zType, i+1, pEList->nExpr, 0);
return 1;
}
- resolveAlias(pParse, pEList, pItem->u.x.iOrderByCol-1, pItem->pExpr,
- zType,0);
+ resolveAlias(pParse, pEList, pItem->u.x.iOrderByCol-1, pItem->pExpr,0);
}
}
return 0;
@@ -104376,7 +108346,7 @@ static int resolveOrderGroupBy(
Parse *pParse; /* Parsing context */
int nResult; /* Number of terms in the result set */
- if( pOrderBy==0 ) return 0;
+ assert( pOrderBy!=0 );
nResult = pSelect->pEList->nExpr;
pParse = pNC->pParse;
for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
@@ -104399,7 +108369,7 @@ static int resolveOrderGroupBy(
** number so that sqlcipher_sqlite3ResolveOrderGroupBy() will convert the
** order-by term to a copy of the result-set expression */
if( iCol<1 || iCol>0xffff ){
- resolveOutOfRangeError(pParse, zType, i+1, nResult);
+ resolveOutOfRangeError(pParse, zType, i+1, nResult, pE2);
return 1;
}
pItem->u.x.iOrderByCol = (u16)iCol;
@@ -104457,7 +108427,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
*/
if( (p->selFlags & SF_Expanded)==0 ){
sqlcipher_sqlite3SelectPrep(pParse, p, pOuterNC);
- return (pParse->nErr || db->mallocFailed) ? WRC_Abort : WRC_Prune;
+ return pParse->nErr ? WRC_Abort : WRC_Prune;
}
isCompound = p->pPrior!=0;
@@ -104466,8 +108436,10 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
while( p ){
assert( (p->selFlags & SF_Expanded)!=0 );
assert( (p->selFlags & SF_Resolved)==0 );
+ assert( db->suppressErr==0 ); /* SF_Resolved not set if errors suppressed */
p->selFlags |= SF_Resolved;
+
/* Resolve the expressions in the LIMIT and OFFSET clauses. These
** are not allowed to refer to any names, so pass an empty NameContext.
*/
@@ -104492,30 +108464,30 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
p->pOrderBy = 0;
}
- /* Recursively resolve names in all subqueries
+ /* Recursively resolve names in all subqueries in the FROM clause
*/
for(i=0; i<p->pSrc->nSrc; i++){
- struct SrcList_item *pItem = &p->pSrc->a[i];
+ SrcItem *pItem = &p->pSrc->a[i];
if( pItem->pSelect && (pItem->pSelect->selFlags & SF_Resolved)==0 ){
- NameContext *pNC; /* Used to iterate name contexts */
- int nRef = 0; /* Refcount for pOuterNC and outer contexts */
+ int nRef = pOuterNC ? pOuterNC->nRef : 0;
const char *zSavedContext = pParse->zAuthContext;
- /* Count the total number of references to pOuterNC and all of its
- ** parent contexts. After resolving references to expressions in
- ** pItem->pSelect, check if this value has changed. If so, then
- ** SELECT statement pItem->pSelect must be correlated. Set the
- ** pItem->fg.isCorrelated flag if this is the case. */
- for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef += pNC->nRef;
-
if( pItem->zName ) pParse->zAuthContext = pItem->zName;
sqlcipher_sqlite3ResolveSelectNames(pParse, pItem->pSelect, pOuterNC);
pParse->zAuthContext = zSavedContext;
- if( pParse->nErr || db->mallocFailed ) return WRC_Abort;
+ if( pParse->nErr ) return WRC_Abort;
+ assert( db->mallocFailed==0 );
- for(pNC=pOuterNC; pNC; pNC=pNC->pNext) nRef -= pNC->nRef;
- assert( pItem->fg.isCorrelated==0 && nRef<=0 );
- pItem->fg.isCorrelated = (nRef!=0);
+ /* If the number of references to the outer context changed when
+ ** expressions in the sub-select were resolved, the sub-select
+ ** is correlated. It is not required to check the refcount on any
+ ** but the innermost outer context object, as lookupName() increments
+ ** the refcount on all contexts between the current one and the
+ ** context containing the column when it resolves a name. */
+ if( pOuterNC ){
+ assert( pItem->fg.isCorrelated==0 && pOuterNC->nRef>=nRef );
+ pItem->fg.isCorrelated = (pOuterNC->nRef>nRef);
+ }
}
}
@@ -104537,18 +108509,12 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
pGroupBy = p->pGroupBy;
if( pGroupBy || (sNC.ncFlags & NC_HasAgg)!=0 ){
assert( NC_MinMaxAgg==SF_MinMaxAgg );
- p->selFlags |= SF_Aggregate | (sNC.ncFlags&NC_MinMaxAgg);
+ assert( NC_OrderAgg==SF_OrderByReqd );
+ p->selFlags |= SF_Aggregate | (sNC.ncFlags&(NC_MinMaxAgg|NC_OrderAgg));
}else{
sNC.ncFlags &= ~NC_AllowAgg;
}
- /* If a HAVING clause is present, then there must be a GROUP BY clause.
- */
- if( p->pHaving && !pGroupBy ){
- sqlcipher_sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING");
- return WRC_Abort;
- }
-
/* 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
@@ -104557,15 +108523,21 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
** Minor point: If this is the case, then the expression will be
** re-evaluated for each reference to it.
*/
- assert( (sNC.ncFlags & (NC_UAggInfo|NC_UUpsert))==0 );
+ assert( (sNC.ncFlags & (NC_UAggInfo|NC_UUpsert|NC_UBaseReg))==0 );
sNC.uNC.pEList = p->pEList;
sNC.ncFlags |= NC_UEList;
- if( sqlcipher_sqlite3ResolveExprNames(&sNC, p->pHaving) ) return WRC_Abort;
+ if( p->pHaving ){
+ if( (p->selFlags & SF_Aggregate)==0 ){
+ sqlcipher_sqlite3ErrorMsg(pParse, "HAVING clause on a non-aggregate query");
+ return WRC_Abort;
+ }
+ if( sqlcipher_sqlite3ResolveExprNames(&sNC, p->pHaving) ) return WRC_Abort;
+ }
if( sqlcipher_sqlite3ResolveExprNames(&sNC, p->pWhere) ) return WRC_Abort;
/* Resolve names in table-valued-function arguments */
for(i=0; i<p->pSrc->nSrc; i++){
- struct SrcList_item *pItem = &p->pSrc->a[i];
+ SrcItem *pItem = &p->pSrc->a[i];
if( pItem->fg.isTabFunc
&& sqlcipher_sqlite3ResolveExprListNames(&sNC, pItem->u1.pFuncArg)
){
@@ -104573,6 +108545,19 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
}
}
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ if( IN_RENAME_OBJECT ){
+ Window *pWin;
+ for(pWin=p->pWinDefn; pWin; pWin=pWin->pNextWin){
+ if( sqlcipher_sqlite3ResolveExprListNames(&sNC, pWin->pOrderBy)
+ || sqlcipher_sqlite3ResolveExprListNames(&sNC, pWin->pPartition)
+ ){
+ return WRC_Abort;
+ }
+ }
+ }
+#endif
+
/* The ORDER BY and GROUP BY clauses may not refer to terms in
** outer queries
*/
@@ -104600,7 +108585,8 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
** is not detected until much later, and so we need to go ahead and
** resolve those symbols on the incorrect ORDER BY for consistency.
*/
- if( isCompound<=nCompound /* Defer right-most ORDER BY of a compound */
+ if( p->pOrderBy!=0
+ && isCompound<=nCompound /* Defer right-most ORDER BY of a compound */
&& resolveOrderGroupBy(&sNC, p, p->pOrderBy, "ORDER")
){
return WRC_Abort;
@@ -104628,19 +108614,6 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
}
}
-#ifndef SQLITE_OMIT_WINDOWFUNC
- if( IN_RENAME_OBJECT ){
- Window *pWin;
- for(pWin=p->pWinDefn; pWin; pWin=pWin->pNextWin){
- if( sqlcipher_sqlite3ResolveExprListNames(&sNC, pWin->pOrderBy)
- || sqlcipher_sqlite3ResolveExprListNames(&sNC, pWin->pPartition)
- ){
- return WRC_Abort;
- }
- }
- }
-#endif
-
/* If this is part of a compound SELECT, check that it has the right
** number of expressions in the select list. */
if( p->pNext && p->pEList->nExpr!=p->pNext->pEList->nExpr ){
@@ -104720,11 +108693,11 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ResolveExprNames(
Walker w;
if( pExpr==0 ) return SQLITE_OK;
- savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
- pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
+ savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg);
+ pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg);
w.pParse = pNC->pParse;
w.xExprCallback = resolveExprStep;
- w.xSelectCallback = resolveSelectStep;
+ w.xSelectCallback = (pNC->ncFlags & NC_NoSelect) ? 0 : resolveSelectStep;
w.xSelectCallback2 = 0;
w.u.pNC = pNC;
#if SQLITE_MAX_EXPR_DEPTH>0
@@ -104743,7 +108716,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ResolveExprNames(
testcase( pNC->ncFlags & NC_HasWin );
ExprSetProperty(pExpr, pNC->ncFlags & (NC_HasAgg|NC_HasWin) );
pNC->ncFlags |= savedHasAgg;
- return pNC->nErr>0 || w.pParse->nErr>0;
+ return pNC->nNcErr>0 || w.pParse->nErr>0;
}
/*
@@ -104764,8 +108737,8 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ResolveExprListNames(
w.xSelectCallback = resolveSelectStep;
w.xSelectCallback2 = 0;
w.u.pNC = pNC;
- savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
- pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
+ savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg);
+ pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg);
for(i=0; i<pList->nExpr; i++){
Expr *pExpr = pList->a[i].pExpr;
if( pExpr==0 ) continue;
@@ -104783,12 +108756,13 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ResolveExprListNames(
assert( EP_Win==NC_HasWin );
testcase( pNC->ncFlags & NC_HasAgg );
testcase( pNC->ncFlags & NC_HasWin );
- if( pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin) ){
+ if( pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg) ){
ExprSetProperty(pExpr, pNC->ncFlags & (NC_HasAgg|NC_HasWin) );
- savedHasAgg |= pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
- pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
+ savedHasAgg |= pNC->ncFlags &
+ (NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg);
+ pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg);
}
- if( pNC->nErr>0 || w.pParse->nErr>0 ) return WRC_Abort;
+ if( w.pParse->nErr>0 ) return WRC_Abort;
}
pNC->ncFlags |= savedHasAgg;
return WRC_Continue;
@@ -104900,9 +108874,9 @@ static int exprCodeVector(Parse *pParse, Expr *p, int *piToFree);
/*
** Return the affinity character for a single column of a table.
*/
-SQLITE_PRIVATE char sqlcipher_sqlite3TableColumnAffinity(Table *pTab, int iCol){
- assert( iCol<pTab->nCol );
- return iCol>=0 ? pTab->aCol[iCol].affinity : SQLITE_AFF_INTEGER;
+SQLITE_PRIVATE char sqlcipher_sqlite3TableColumnAffinity(const Table *pTab, int iCol){
+ if( iCol<0 || NEVER(iCol>=pTab->nCol) ) return SQLITE_AFF_INTEGER;
+ return pTab->aCol[iCol].affinity;
}
/*
@@ -104931,30 +108905,36 @@ SQLITE_PRIVATE char sqlcipher_sqlite3ExprAffinity(const Expr *pExpr){
assert( pExpr!=0 );
}
op = pExpr->op;
+ if( op==TK_REGISTER ) op = pExpr->op2;
+ if( op==TK_COLUMN || op==TK_AGG_COLUMN ){
+ assert( ExprUseYTab(pExpr) );
+ if( pExpr->y.pTab ){
+ return sqlcipher_sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
+ }
+ }
if( op==TK_SELECT ){
- assert( pExpr->flags&EP_xIsSelect );
+ assert( ExprUseXSelect(pExpr) );
assert( pExpr->x.pSelect!=0 );
assert( pExpr->x.pSelect->pEList!=0 );
assert( pExpr->x.pSelect->pEList->a[0].pExpr!=0 );
return sqlcipher_sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr);
}
- if( op==TK_REGISTER ) op = pExpr->op2;
#ifndef SQLITE_OMIT_CAST
if( op==TK_CAST ){
assert( !ExprHasProperty(pExpr, EP_IntValue) );
return sqlcipher_sqlite3AffinityType(pExpr->u.zToken, 0);
}
#endif
- if( (op==TK_AGG_COLUMN || op==TK_COLUMN) && pExpr->y.pTab ){
- return sqlcipher_sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
- }
if( op==TK_SELECT_COLUMN ){
- assert( pExpr->pLeft->flags&EP_xIsSelect );
+ assert( pExpr->pLeft!=0 && ExprUseXSelect(pExpr->pLeft) );
+ assert( pExpr->iColumn < pExpr->iTable );
+ assert( pExpr->iTable==pExpr->pLeft->x.pSelect->pEList->nExpr );
return sqlcipher_sqlite3ExprAffinity(
pExpr->pLeft->x.pSelect->pEList->a[pExpr->iColumn].pExpr
);
}
if( op==TK_VECTOR ){
+ assert( ExprUseXList(pExpr) );
return sqlcipher_sqlite3ExprAffinity(pExpr->x.pList->a[0].pExpr);
}
return pExpr->affExpr;
@@ -104969,7 +108949,7 @@ SQLITE_PRIVATE char sqlcipher_sqlite3ExprAffinity(const Expr *pExpr){
** and the pExpr parameter is returned unchanged.
*/
SQLITE_PRIVATE Expr *sqlcipher_sqlite3ExprAddCollateToken(
- Parse *pParse, /* Parsing context */
+ const Parse *pParse, /* Parsing context */
Expr *pExpr, /* Add the "COLLATE" clause to this expression */
const Token *pCollName, /* Name of collating sequence */
int dequote /* True to dequote pCollName */
@@ -104984,7 +108964,11 @@ SQLITE_PRIVATE Expr *sqlcipher_sqlite3ExprAddCollateToken(
}
return pExpr;
}
-SQLITE_PRIVATE Expr *sqlcipher_sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){
+SQLITE_PRIVATE Expr *sqlcipher_sqlite3ExprAddCollateString(
+ const Parse *pParse, /* Parsing context */
+ Expr *pExpr, /* Add the "COLLATE" clause to this expression */
+ const char *zC /* The collating sequence name */
+){
Token s;
assert( zC!=0 );
sqlcipher_sqlite3TokenInit(&s, (char*)zC);
@@ -105010,7 +108994,7 @@ SQLITE_PRIVATE Expr *sqlcipher_sqlite3ExprSkipCollate(Expr *pExpr){
SQLITE_PRIVATE Expr *sqlcipher_sqlite3ExprSkipCollateAndLikely(Expr *pExpr){
while( pExpr && ExprHasProperty(pExpr, EP_Skip|EP_Unlikely) ){
if( ExprHasProperty(pExpr, EP_Unlikely) ){
- assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
+ assert( ExprUseXList(pExpr) );
assert( pExpr->x.pList->nExpr>0 );
assert( pExpr->op==TK_FUNCTION );
pExpr = pExpr->x.pList->a[0].pExpr;
@@ -105043,27 +109027,30 @@ SQLITE_PRIVATE CollSeq *sqlcipher_sqlite3ExprCollSeq(Parse *pParse, const Expr *
while( p ){
int op = p->op;
if( op==TK_REGISTER ) op = p->op2;
- if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_TRIGGER)
- && p->y.pTab!=0
- ){
- /* op==TK_REGISTER && p->y.pTab!=0 happens when pExpr was originally
- ** a TK_COLUMN but was previously evaluated and cached in a register */
- int j = p->iColumn;
- if( j>=0 ){
- const char *zColl = p->y.pTab->aCol[j].zColl;
- pColl = sqlcipher_sqlite3FindCollSeq(db, ENC(db), zColl, 0);
+ if( op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_TRIGGER ){
+ assert( ExprUseYTab(p) );
+ if( p->y.pTab!=0 ){
+ /* op==TK_REGISTER && p->y.pTab!=0 happens when pExpr was originally
+ ** a TK_COLUMN but was previously evaluated and cached in a register */
+ int j = p->iColumn;
+ if( j>=0 ){
+ const char *zColl = sqlcipher_sqlite3ColumnColl(&p->y.pTab->aCol[j]);
+ pColl = sqlcipher_sqlite3FindCollSeq(db, ENC(db), zColl, 0);
+ }
+ break;
}
- break;
}
if( op==TK_CAST || op==TK_UPLUS ){
p = p->pLeft;
continue;
}
if( op==TK_VECTOR ){
+ assert( ExprUseXList(p) );
p = p->x.pList->a[0].pExpr;
continue;
}
if( op==TK_COLLATE ){
+ assert( !ExprHasProperty(p, EP_IntValue) );
pColl = sqlcipher_sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken);
break;
}
@@ -105073,11 +109060,9 @@ SQLITE_PRIVATE CollSeq *sqlcipher_sqlite3ExprCollSeq(Parse *pParse, const Expr *
}else{
Expr *pNext = p->pRight;
/* The Expr.x union is never used at the same time as Expr.pRight */
+ assert( ExprUseXList(p) );
assert( p->x.pList==0 || p->pRight==0 );
- if( p->x.pList!=0
- && !db->mallocFailed
- && ALWAYS(!ExprHasProperty(p, EP_xIsSelect))
- ){
+ if( p->x.pList!=0 && !db->mallocFailed ){
int i;
for(i=0; ALWAYS(i<p->x.pList->nExpr); i++){
if( ExprHasProperty(p->x.pList->a[i].pExpr, EP_Collate) ){
@@ -105160,7 +109145,7 @@ static char comparisonAffinity(const Expr *pExpr){
aff = sqlcipher_sqlite3ExprAffinity(pExpr->pLeft);
if( pExpr->pRight ){
aff = sqlcipher_sqlite3CompareAffinity(pExpr->pRight, aff);
- }else if( ExprHasProperty(pExpr, EP_xIsSelect) ){
+ }else if( ExprUseXSelect(pExpr) ){
aff = sqlcipher_sqlite3CompareAffinity(pExpr->x.pSelect->pEList->a[0].pExpr, aff);
}else if( aff==0 ){
aff = SQLITE_AFF_BLOB;
@@ -105286,7 +109271,7 @@ static int codeCompare(
** But a TK_SELECT might be either a vector or a scalar. It is only
** considered a vector if it has two or more result columns.
*/
-SQLITE_PRIVATE int sqlcipher_sqlite3ExprIsVector(Expr *pExpr){
+SQLITE_PRIVATE int sqlcipher_sqlite3ExprIsVector(const Expr *pExpr){
return sqlcipher_sqlite3ExprVectorSize(pExpr)>1;
}
@@ -105296,12 +109281,14 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ExprIsVector(Expr *pExpr){
** is a sub-select, return the number of columns in the sub-select. For
** any other type of expression, return 1.
*/
-SQLITE_PRIVATE int sqlcipher_sqlite3ExprVectorSize(Expr *pExpr){
+SQLITE_PRIVATE int sqlcipher_sqlite3ExprVectorSize(const Expr *pExpr){
u8 op = pExpr->op;
if( op==TK_REGISTER ) op = pExpr->op2;
if( op==TK_VECTOR ){
+ assert( ExprUseXList(pExpr) );
return pExpr->x.pList->nExpr;
}else if( op==TK_SELECT ){
+ assert( ExprUseXSelect(pExpr) );
return pExpr->x.pSelect->pEList->nExpr;
}else{
return 1;
@@ -105324,12 +109311,14 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ExprVectorSize(Expr *pExpr){
** been positioned.
*/
SQLITE_PRIVATE Expr *sqlcipher_sqlite3VectorFieldSubexpr(Expr *pVector, int i){
- assert( i<sqlcipher_sqlite3ExprVectorSize(pVector) );
+ assert( i<sqlcipher_sqlite3ExprVectorSize(pVector) || pVector->op==TK_ERROR );
if( sqlcipher_sqlite3ExprIsVector(pVector) ){
assert( pVector->op2==0 || pVector->op==TK_REGISTER );
if( pVector->op==TK_SELECT || pVector->op2==TK_SELECT ){
+ assert( ExprUseXSelect(pVector) );
return pVector->x.pSelect->pEList->a[i].pExpr;
}else{
+ assert( ExprUseXList(pVector) );
return pVector->x.pList->a[i].pExpr;
}
}
@@ -105360,11 +109349,12 @@ SQLITE_PRIVATE Expr *sqlcipher_sqlite3VectorFieldSubexpr(Expr *pVector, int i){
SQLITE_PRIVATE Expr *sqlcipher_sqlite3ExprForVectorField(
Parse *pParse, /* Parsing context */
Expr *pVector, /* The vector. List of expressions or a sub-SELECT */
- int iField /* Which column of the vector to return */
+ int iField, /* Which column of the vector to return */
+ int nField /* Total number of columns in the vector */
){
Expr *pRet;
if( pVector->op==TK_SELECT ){
- assert( pVector->flags & EP_xIsSelect );
+ assert( ExprUseXSelect(pVector) );
/* The TK_SELECT_COLUMN Expr node:
**
** pLeft: pVector containing TK_SELECT. Not deleted.
@@ -105383,14 +109373,23 @@ SQLITE_PRIVATE Expr *sqlcipher_sqlite3ExprForVectorField(
*/
pRet = sqlcipher_sqlite3PExpr(pParse, TK_SELECT_COLUMN, 0, 0);
if( pRet ){
+ pRet->iTable = nField;
pRet->iColumn = iField;
pRet->pLeft = pVector;
}
- assert( pRet==0 || pRet->iTable==0 );
}else{
- if( pVector->op==TK_VECTOR ) pVector = pVector->x.pList->a[iField].pExpr;
+ if( pVector->op==TK_VECTOR ){
+ Expr **ppVector;
+ assert( ExprUseXList(pVector) );
+ ppVector = &pVector->x.pList->a[iField].pExpr;
+ pVector = *ppVector;
+ if( IN_RENAME_OBJECT ){
+ /* This must be a vector UPDATE inside a trigger */
+ *ppVector = 0;
+ return pVector;
+ }
+ }
pRet = sqlcipher_sqlite3ExprDup(pParse->db, pVector, 0);
- sqlcipher_sqlite3RenameTokenRemap(pParse, pRet, pVector);
}
return pRet;
}
@@ -105440,17 +109439,22 @@ static int exprVectorRegister(
int *pRegFree /* OUT: Temp register to free */
){
u8 op = pVector->op;
- assert( op==TK_VECTOR || op==TK_REGISTER || op==TK_SELECT );
+ assert( op==TK_VECTOR || op==TK_REGISTER || op==TK_SELECT || op==TK_ERROR );
if( op==TK_REGISTER ){
*ppExpr = sqlcipher_sqlite3VectorFieldSubexpr(pVector, iField);
return pVector->iTable+iField;
}
if( op==TK_SELECT ){
+ assert( ExprUseXSelect(pVector) );
*ppExpr = pVector->x.pSelect->pEList->a[iField].pExpr;
return regSelect+iField;
}
- *ppExpr = pVector->x.pList->a[iField].pExpr;
- return sqlcipher_sqlite3ExprCodeTemp(pParse, *ppExpr, pRegFree);
+ if( op==TK_VECTOR ){
+ assert( ExprUseXList(pVector) );
+ *ppExpr = pVector->x.pList->a[iField].pExpr;
+ return sqlcipher_sqlite3ExprCodeTemp(pParse, *ppExpr, pRegFree);
+ }
+ return 0;
}
/*
@@ -105479,6 +109483,7 @@ static void codeVectorCompare(
int regLeft = 0;
int regRight = 0;
u8 opx = op;
+ int addrCmp = 0;
int addrDone = sqlcipher_sqlite3VdbeMakeLabel(pParse);
int isCommuted = ExprHasProperty(pExpr,EP_Commuted);
@@ -105498,21 +109503,24 @@ static void codeVectorCompare(
assert( p5==0 || pExpr->op!=op );
assert( p5==SQLITE_NULLEQ || pExpr->op==op );
- p5 |= SQLITE_STOREP2;
- if( opx==TK_LE ) opx = TK_LT;
- if( opx==TK_GE ) opx = TK_GT;
+ if( op==TK_LE ) opx = TK_LT;
+ if( op==TK_GE ) opx = TK_GT;
+ if( op==TK_NE ) opx = TK_EQ;
regLeft = exprCodeSubselect(pParse, pLeft);
regRight = exprCodeSubselect(pParse, pRight);
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_Integer, 1, dest);
for(i=0; 1 /*Loop exits by "break"*/; i++){
int regFree1 = 0, regFree2 = 0;
- Expr *pL, *pR;
+ Expr *pL = 0, *pR = 0;
int r1, r2;
assert( i>=0 && i<nLeft );
+ if( addrCmp ) sqlcipher_sqlite3VdbeJumpHere(v, addrCmp);
r1 = exprVectorRegister(pParse, pLeft, i, regLeft, &pL, &regFree1);
r2 = exprVectorRegister(pParse, pRight, i, regRight, &pR, &regFree2);
- codeCompare(pParse, pL, pR, opx, r1, r2, dest, p5, isCommuted);
+ addrCmp = sqlcipher_sqlite3VdbeCurrentAddr(v);
+ codeCompare(pParse, pL, pR, opx, r1, r2, addrDone, p5, isCommuted);
testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt);
@@ -105521,26 +109529,32 @@ static void codeVectorCompare(
testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne);
sqlcipher_sqlite3ReleaseTempReg(pParse, regFree1);
sqlcipher_sqlite3ReleaseTempReg(pParse, regFree2);
+ if( (opx==TK_LT || opx==TK_GT) && i<nLeft-1 ){
+ addrCmp = sqlcipher_sqlite3VdbeAddOp0(v, OP_ElseEq);
+ testcase(opx==TK_LT); VdbeCoverageIf(v,opx==TK_LT);
+ testcase(opx==TK_GT); VdbeCoverageIf(v,opx==TK_GT);
+ }
+ if( p5==SQLITE_NULLEQ ){
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_Integer, 0, dest);
+ }else{
+ sqlcipher_sqlite3VdbeAddOp3(v, OP_ZeroOrNull, r1, dest, r2);
+ }
if( i==nLeft-1 ){
break;
}
if( opx==TK_EQ ){
- sqlcipher_sqlite3VdbeAddOp2(v, OP_IfNot, dest, addrDone); VdbeCoverage(v);
- p5 |= SQLITE_KEEPNULL;
- }else if( opx==TK_NE ){
- sqlcipher_sqlite3VdbeAddOp2(v, OP_If, dest, addrDone); VdbeCoverage(v);
- p5 |= SQLITE_KEEPNULL;
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_NotNull, dest, addrDone); VdbeCoverage(v);
}else{
assert( op==TK_LT || op==TK_GT || op==TK_LE || op==TK_GE );
- sqlcipher_sqlite3VdbeAddOp2(v, OP_ElseNotEq, 0, addrDone);
- VdbeCoverageIf(v, op==TK_LT);
- VdbeCoverageIf(v, op==TK_GT);
- VdbeCoverageIf(v, op==TK_LE);
- VdbeCoverageIf(v, op==TK_GE);
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_Goto, 0, addrDone);
if( i==nLeft-2 ) opx = op;
}
}
+ sqlcipher_sqlite3VdbeJumpHere(v, addrCmp);
sqlcipher_sqlite3VdbeResolveLabel(v, addrDone);
+ if( op==TK_NE ){
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_Not, dest, dest);
+ }
}
#if SQLITE_MAX_EXPR_DEPTH>0
@@ -105570,14 +109584,14 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ExprCheckHeight(Parse *pParse, int nHeight){
** to by pnHeight, the second parameter, then set *pnHeight to that
** value.
*/
-static void heightOfExpr(Expr *p, int *pnHeight){
+static void heightOfExpr(const Expr *p, int *pnHeight){
if( p ){
if( p->nHeight>*pnHeight ){
*pnHeight = p->nHeight;
}
}
}
-static void heightOfExprList(ExprList *p, int *pnHeight){
+static void heightOfExprList(const ExprList *p, int *pnHeight){
if( p ){
int i;
for(i=0; i<p->nExpr; i++){
@@ -105585,8 +109599,8 @@ static void heightOfExprList(ExprList *p, int *pnHeight){
}
}
}
-static void heightOfSelect(Select *pSelect, int *pnHeight){
- Select *p;
+static void heightOfSelect(const Select *pSelect, int *pnHeight){
+ const Select *p;
for(p=pSelect; p; p=p->pPrior){
heightOfExpr(p->pWhere, pnHeight);
heightOfExpr(p->pHaving, pnHeight);
@@ -105608,10 +109622,9 @@ static void heightOfSelect(Select *pSelect, int *pnHeight){
** if appropriate.
*/
static void exprSetHeight(Expr *p){
- int nHeight = 0;
- heightOfExpr(p->pLeft, &nHeight);
- heightOfExpr(p->pRight, &nHeight);
- if( ExprHasProperty(p, EP_xIsSelect) ){
+ int nHeight = p->pLeft ? p->pLeft->nHeight : 0;
+ if( p->pRight && p->pRight->nHeight>nHeight ) nHeight = p->pRight->nHeight;
+ if( ExprUseXSelect(p) ){
heightOfSelect(p->x.pSelect, &nHeight);
}else if( p->x.pList ){
heightOfExprList(p->x.pList, &nHeight);
@@ -105638,7 +109651,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *
** Return the maximum height of any expression tree referenced
** by the select statement passed as an argument.
*/
-SQLITE_PRIVATE int sqlcipher_sqlite3SelectExprHeight(Select *p){
+SQLITE_PRIVATE int sqlcipher_sqlite3SelectExprHeight(const Select *p){
int nHeight = 0;
heightOfSelect(p, &nHeight);
return nHeight;
@@ -105650,7 +109663,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3SelectExprHeight(Select *p){
*/
SQLITE_PRIVATE void sqlcipher_sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){
if( pParse->nErr ) return;
- if( p && p->x.pList && !ExprHasProperty(p, EP_xIsSelect) ){
+ if( p && ExprUseXList(p) && p->x.pList ){
p->flags |= EP_Propagate & sqlcipher_sqlite3ExprListFlags(p->x.pList);
}
}
@@ -105808,6 +109821,63 @@ SQLITE_PRIVATE void sqlcipher_sqlite3PExprAddSelect(Parse *pParse, Expr *pExpr,
}
}
+/*
+** Expression list pEList is a list of vector values. This function
+** converts the contents of pEList to a VALUES(...) Select statement
+** returning 1 row for each element of the list. For example, the
+** expression list:
+**
+** ( (1,2), (3,4) (5,6) )
+**
+** is translated to the equivalent of:
+**
+** VALUES(1,2), (3,4), (5,6)
+**
+** Each of the vector values in pEList must contain exactly nElem terms.
+** If a list element that is not a vector or does not contain nElem terms,
+** an error message is left in pParse.
+**
+** This is used as part of processing IN(...) expressions with a list
+** of vectors on the RHS. e.g. "... IN ((1,2), (3,4), (5,6))".
+*/
+SQLITE_PRIVATE Select *sqlcipher_sqlite3ExprListToValues(Parse *pParse, int nElem, ExprList *pEList){
+ int ii;
+ Select *pRet = 0;
+ assert( nElem>1 );
+ for(ii=0; ii<pEList->nExpr; ii++){
+ Select *pSel;
+ Expr *pExpr = pEList->a[ii].pExpr;
+ int nExprElem;
+ if( pExpr->op==TK_VECTOR ){
+ assert( ExprUseXList(pExpr) );
+ nExprElem = pExpr->x.pList->nExpr;
+ }else{
+ nExprElem = 1;
+ }
+ if( nExprElem!=nElem ){
+ sqlcipher_sqlite3ErrorMsg(pParse, "IN(...) element has %d term%s - expected %d",
+ nExprElem, nExprElem>1?"s":"", nElem
+ );
+ break;
+ }
+ assert( ExprUseXList(pExpr) );
+ pSel = sqlcipher_sqlite3SelectNew(pParse, pExpr->x.pList, 0, 0, 0, 0, 0, SF_Values,0);
+ pExpr->x.pList = 0;
+ if( pSel ){
+ if( pRet ){
+ pSel->op = TK_ALL;
+ pSel->pPrior = pRet;
+ }
+ pRet = pSel;
+ }
+ }
+
+ if( pRet && pRet->pPrior ){
+ pRet->selFlags |= SF_MultiValue;
+ }
+ sqlcipher_sqlite3ExprListDelete(pParse->db, pEList);
+ return pRet;
+}
/*
** Join two expressions using an AND operator. If either expression is
@@ -105826,8 +109896,8 @@ SQLITE_PRIVATE Expr *sqlcipher_sqlite3ExprAnd(Parse *pParse, Expr *pLeft, Expr *
}else if( (ExprAlwaysFalse(pLeft) || ExprAlwaysFalse(pRight))
&& !IN_RENAME_OBJECT
){
- sqlcipher_sqlite3ExprDelete(db, pLeft);
- sqlcipher_sqlite3ExprDelete(db, pRight);
+ sqlcipher_sqlite3ExprDeferredDelete(pParse, pLeft);
+ sqlcipher_sqlite3ExprDeferredDelete(pParse, pRight);
return sqlcipher_sqlite3Expr(db, TK_INTEGER, "0");
}else{
return sqlcipher_sqlite3PExpr(pParse, TK_AND, pLeft, pRight);
@@ -105841,7 +109911,7 @@ SQLITE_PRIVATE Expr *sqlcipher_sqlite3ExprAnd(Parse *pParse, Expr *pLeft, Expr *
SQLITE_PRIVATE Expr *sqlcipher_sqlite3ExprFunction(
Parse *pParse, /* Parsing context */
ExprList *pList, /* Argument list */
- Token *pToken, /* Name of the function */
+ const Token *pToken, /* Name of the function */
int eDistinct /* SF_Distinct or SF_ALL or 0 */
){
Expr *pNew;
@@ -105852,12 +109922,17 @@ SQLITE_PRIVATE Expr *sqlcipher_sqlite3ExprFunction(
sqlcipher_sqlite3ExprListDelete(db, pList); /* Avoid memory leak when malloc fails */
return 0;
}
- if( pList && pList->nExpr > pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){
+ assert( !ExprHasProperty(pNew, EP_InnerON|EP_OuterON) );
+ pNew->w.iOfst = (int)(pToken->z - pParse->zTail);
+ if( pList
+ && pList->nExpr > pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG]
+ && !pParse->nested
+ ){
sqlcipher_sqlite3ErrorMsg(pParse, "too many arguments on function %T", pToken);
}
pNew->x.pList = pList;
ExprSetProperty(pNew, EP_HasFunc);
- assert( !ExprHasProperty(pNew, EP_xIsSelect) );
+ assert( ExprUseXList(pNew) );
sqlcipher_sqlite3ExprSetHeightAndFlags(pParse, pNew);
if( eDistinct==SF_Distinct ) ExprSetProperty(pNew, EP_Distinct);
return pNew;
@@ -105876,8 +109951,8 @@ SQLITE_PRIVATE Expr *sqlcipher_sqlite3ExprFunction(
*/
SQLITE_PRIVATE void sqlcipher_sqlite3ExprFunctionUsable(
Parse *pParse, /* Parsing and code generating context */
- Expr *pExpr, /* The function invocation */
- FuncDef *pDef /* The function being invoked */
+ const Expr *pExpr, /* The function invocation */
+ const FuncDef *pDef /* The function being invoked */
){
assert( !IN_RENAME_OBJECT );
assert( (pDef->funcFlags & (SQLITE_FUNC_DIRECT|SQLITE_FUNC_UNSAFE))!=0 );
@@ -105892,7 +109967,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3ExprFunctionUsable(
** SQLITE_DBCONFIG_TRUSTED_SCHEMA is off (meaning
** that the schema is possibly tainted).
*/
- sqlcipher_sqlite3ErrorMsg(pParse, "unsafe use of %s()", pDef->zName);
+ sqlcipher_sqlite3ErrorMsg(pParse, "unsafe use of %#T()", pExpr);
}
}
}
@@ -105948,6 +110023,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pE
if( bOk==0 || i<1 || i>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){
sqlcipher_sqlite3ErrorMsg(pParse, "variable number must be between ?1 and ?%d",
db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]);
+ sqlcipher_sqlite3RecordErrorOffsetOfExpr(pParse->db, pExpr);
return;
}
x = (ynVar)i;
@@ -105975,6 +110051,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pE
pExpr->iColumn = x;
if( x>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){
sqlcipher_sqlite3ErrorMsg(pParse, "too many SQL variables");
+ sqlcipher_sqlite3RecordErrorOffsetOfExpr(pParse->db, pExpr);
}
}
@@ -105983,27 +110060,26 @@ SQLITE_PRIVATE void sqlcipher_sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pE
*/
static SQLITE_NOINLINE void sqlcipher_sqlite3ExprDeleteNN(sqlcipher_sqlite3 *db, Expr *p){
assert( p!=0 );
- /* Sanity check: Assert that the IntValue is non-negative if it exists */
- assert( !ExprHasProperty(p, EP_IntValue) || p->u.iValue>=0 );
-
- assert( !ExprHasProperty(p, EP_WinFunc) || p->y.pWin!=0 || db->mallocFailed );
- assert( p->op!=TK_FUNCTION || ExprHasProperty(p, EP_TokenOnly|EP_Reduced)
- || p->y.pWin==0 || ExprHasProperty(p, EP_WinFunc) );
+ assert( !ExprUseUValue(p) || p->u.iValue>=0 );
+ assert( !ExprUseYWin(p) || !ExprUseYSub(p) );
+ assert( !ExprUseYWin(p) || p->y.pWin!=0 || db->mallocFailed );
+ assert( p->op!=TK_FUNCTION || !ExprUseYSub(p) );
#ifdef SQLITE_DEBUG
if( ExprHasProperty(p, EP_Leaf) && !ExprHasProperty(p, EP_TokenOnly) ){
assert( p->pLeft==0 );
assert( p->pRight==0 );
- assert( p->x.pSelect==0 );
+ assert( !ExprUseXSelect(p) || p->x.pSelect==0 );
+ assert( !ExprUseXList(p) || p->x.pList==0 );
}
#endif
if( !ExprHasProperty(p, (EP_TokenOnly|EP_Leaf)) ){
/* The Expr.x union is never used at the same time as Expr.pRight */
- assert( p->x.pList==0 || p->pRight==0 );
+ assert( (ExprUseXList(p) && p->x.pList==0) || p->pRight==0 );
if( p->pLeft && p->op!=TK_SELECT_COLUMN ) sqlcipher_sqlite3ExprDeleteNN(db, p->pLeft);
if( p->pRight ){
assert( !ExprHasProperty(p, EP_WinFunc) );
sqlcipher_sqlite3ExprDeleteNN(db, p->pRight);
- }else if( ExprHasProperty(p, EP_xIsSelect) ){
+ }else if( ExprUseXSelect(p) ){
assert( !ExprHasProperty(p, EP_WinFunc) );
sqlcipher_sqlite3SelectDelete(db, p->x.pSelect);
}else{
@@ -106015,7 +110091,10 @@ static SQLITE_NOINLINE void sqlcipher_sqlite3ExprDeleteNN(sqlcipher_sqlite3 *db,
#endif
}
}
- if( ExprHasProperty(p, EP_MemToken) ) sqlcipher_sqlite3DbFree(db, p->u.zToken);
+ if( ExprHasProperty(p, EP_MemToken) ){
+ assert( !ExprHasProperty(p, EP_IntValue) );
+ sqlcipher_sqlite3DbFree(db, p->u.zToken);
+ }
if( !ExprHasProperty(p, EP_Static) ){
sqlcipher_sqlite3DbFreeNN(db, p);
}
@@ -106024,6 +110103,34 @@ SQLITE_PRIVATE void sqlcipher_sqlite3ExprDelete(sqlcipher_sqlite3 *db, Expr *p){
if( p ) sqlcipher_sqlite3ExprDeleteNN(db, p);
}
+/*
+** Clear both elements of an OnOrUsing object
+*/
+SQLITE_PRIVATE void sqlcipher_sqlite3ClearOnOrUsing(sqlcipher_sqlite3 *db, OnOrUsing *p){
+ if( p==0 ){
+ /* Nothing to clear */
+ }else if( p->pOn ){
+ sqlcipher_sqlite3ExprDeleteNN(db, p->pOn);
+ }else if( p->pUsing ){
+ sqlcipher_sqlite3IdListDelete(db, p->pUsing);
+ }
+}
+
+/*
+** Arrange to cause pExpr to be deleted when the pParse is deleted.
+** This is similar to sqlcipher_sqlite3ExprDelete() except that the delete is
+** deferred untilthe pParse is deleted.
+**
+** The pExpr might be deleted immediately on an OOM error.
+**
+** The deferred delete is (currently) implemented by adding the
+** pExpr to the pParse->pConstExpr list with a register number of 0.
+*/
+SQLITE_PRIVATE void sqlcipher_sqlite3ExprDeferredDelete(Parse *pParse, Expr *pExpr){
+ pParse->pConstExpr =
+ sqlcipher_sqlite3ExprListAppend(pParse, pParse->pConstExpr, pExpr);
+}
+
/* Invoke sqlcipher_sqlite3RenameExprUnmap() and sqlcipher_sqlite3ExprDelete() on the
** expression.
*/
@@ -106041,7 +110148,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3ExprUnmapAndDelete(Parse *pParse, Expr *p){
** passed as the first argument. This is always one of EXPR_FULLSIZE,
** EXPR_REDUCEDSIZE or EXPR_TOKENONLYSIZE.
*/
-static int exprStructSize(Expr *p){
+static int exprStructSize(const Expr *p){
if( ExprHasProperty(p, EP_TokenOnly) ) return EXPR_TOKENONLYSIZE;
if( ExprHasProperty(p, EP_Reduced) ) return EXPR_REDUCEDSIZE;
return EXPR_FULLSIZE;
@@ -106081,7 +110188,7 @@ static int exprStructSize(Expr *p){
** of dupedExprStructSize() contain multiple assert() statements that attempt
** to enforce this constraint.
*/
-static int dupedExprStructSize(Expr *p, int flags){
+static int dupedExprStructSize(const Expr *p, int flags){
int nSize;
assert( flags==EXPRDUP_REDUCE || flags==0 ); /* Only one flag value allowed */
assert( EXPR_FULLSIZE<=0xfff );
@@ -106094,7 +110201,7 @@ static int dupedExprStructSize(Expr *p, int flags){
nSize = EXPR_FULLSIZE;
}else{
assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
- assert( !ExprHasProperty(p, EP_FromJoin) );
+ assert( !ExprHasProperty(p, EP_OuterON) );
assert( !ExprHasProperty(p, EP_MemToken) );
assert( !ExprHasVVAProperty(p, EP_NoReduce) );
if( p->pLeft || p->x.pList ){
@@ -106112,7 +110219,7 @@ static int dupedExprStructSize(Expr *p, int flags){
** of the Expr structure and a copy of the Expr.u.zToken string (if that
** string is defined.)
*/
-static int dupedExprNodeSize(Expr *p, int flags){
+static int dupedExprNodeSize(const Expr *p, int flags){
int nByte = dupedExprStructSize(p, flags) & 0xfff;
if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){
nByte += sqlcipher_sqlite3Strlen30NN(p->u.zToken)+1;
@@ -106133,7 +110240,7 @@ static int dupedExprNodeSize(Expr *p, int flags){
** and Expr.pRight variables (but not for any structures pointed to or
** descended from the Expr.x.pList or Expr.x.pSelect variables).
*/
-static int dupedExprSize(Expr *p, int flags){
+static int dupedExprSize(const Expr *p, int flags){
int nByte = 0;
if( p ){
nByte = dupedExprNodeSize(p, flags);
@@ -106152,7 +110259,7 @@ static int dupedExprSize(Expr *p, int flags){
** if any. Before returning, *pzBuffer is set to the first byte past the
** portion of the buffer copied into by this function.
*/
-static Expr *exprDup(sqlcipher_sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){
+static Expr *exprDup(sqlcipher_sqlite3 *db, const Expr *p, int dupFlags, u8 **pzBuffer){
Expr *pNew; /* Value to return */
u8 *zAlloc; /* Memory space from which to build Expr object */
u32 staticFlag; /* EP_Static if space not obtained from malloc */
@@ -106166,6 +110273,7 @@ static Expr *exprDup(sqlcipher_sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer
if( pzBuffer ){
zAlloc = *pzBuffer;
staticFlag = EP_Static;
+ assert( zAlloc!=0 );
}else{
zAlloc = sqlcipher_sqlite3DbMallocRawNN(db, dupedExprSize(p, dupFlags));
staticFlag = 0;
@@ -106214,7 +110322,7 @@ static Expr *exprDup(sqlcipher_sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer
if( 0==((p->flags|pNew->flags) & (EP_TokenOnly|EP_Leaf)) ){
/* Fill in the pNew->x.pSelect or pNew->x.pList member. */
- if( ExprHasProperty(p, EP_xIsSelect) ){
+ if( ExprUseXSelect(p) ){
pNew->x.pSelect = sqlcipher_sqlite3SelectDup(db, p->x.pSelect, dupFlags);
}else{
pNew->x.pList = sqlcipher_sqlite3ExprListDup(db, p->x.pList, dupFlags);
@@ -106243,8 +110351,8 @@ static Expr *exprDup(sqlcipher_sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer
if( !ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){
if( pNew->op==TK_SELECT_COLUMN ){
pNew->pLeft = p->pLeft;
- assert( p->iColumn==0 || p->pRight==0 );
- assert( p->pRight==0 || p->pRight==p->pLeft );
+ assert( p->pRight==0 || p->pRight==p->pLeft
+ || ExprHasProperty(p->pLeft, EP_Subquery) );
}else{
pNew->pLeft = sqlcipher_sqlite3ExprDup(db, p->pLeft, 0);
}
@@ -106261,7 +110369,7 @@ static Expr *exprDup(sqlcipher_sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer
** and the db->mallocFailed flag set.
*/
#ifndef SQLITE_OMIT_CTE
-static With *withDup(sqlcipher_sqlite3 *db, With *p){
+SQLITE_PRIVATE With *sqlcipher_sqlite3WithDup(sqlcipher_sqlite3 *db, With *p){
With *pRet = 0;
if( p ){
sqlcipher_sqlite3_int64 nByte = sizeof(*p) + sizeof(p->a[0]) * (p->nCte-1);
@@ -106273,13 +110381,14 @@ static With *withDup(sqlcipher_sqlite3 *db, With *p){
pRet->a[i].pSelect = sqlcipher_sqlite3SelectDup(db, p->a[i].pSelect, 0);
pRet->a[i].pCols = sqlcipher_sqlite3ExprListDup(db, p->a[i].pCols, 0);
pRet->a[i].zName = sqlcipher_sqlite3DbStrDup(db, p->a[i].zName);
+ pRet->a[i].eM10d = p->a[i].eM10d;
}
}
}
return pRet;
}
#else
-# define withDup(x,y) 0
+# define sqlcipher_sqlite3WithDup(x,y) 0
#endif
#ifndef SQLITE_OMIT_WINDOWFUNC
@@ -106332,20 +110441,23 @@ static void gatherSelectWindows(Select *p){
** truncated version of the usual Expr structure that will be stored as
** part of the in-memory representation of the database schema.
*/
-SQLITE_PRIVATE Expr *sqlcipher_sqlite3ExprDup(sqlcipher_sqlite3 *db, Expr *p, int flags){
+SQLITE_PRIVATE Expr *sqlcipher_sqlite3ExprDup(sqlcipher_sqlite3 *db, const Expr *p, int flags){
assert( flags==0 || flags==EXPRDUP_REDUCE );
return p ? exprDup(db, p, flags, 0) : 0;
}
-SQLITE_PRIVATE ExprList *sqlcipher_sqlite3ExprListDup(sqlcipher_sqlite3 *db, ExprList *p, int flags){
+SQLITE_PRIVATE ExprList *sqlcipher_sqlite3ExprListDup(sqlcipher_sqlite3 *db, const ExprList *p, int flags){
ExprList *pNew;
- struct ExprList_item *pItem, *pOldItem;
+ struct ExprList_item *pItem;
+ const struct ExprList_item *pOldItem;
int i;
- Expr *pPriorSelectCol = 0;
+ Expr *pPriorSelectColOld = 0;
+ Expr *pPriorSelectColNew = 0;
assert( db!=0 );
if( p==0 ) return 0;
pNew = sqlcipher_sqlite3DbMallocRawNN(db, sqlcipher_sqlite3DbMallocSize(db, p));
if( pNew==0 ) return 0;
pNew->nExpr = p->nExpr;
+ pNew->nAlloc = p->nAlloc;
pItem = pNew->a;
pOldItem = p->a;
for(i=0; i<p->nExpr; i++, pItem++, pOldItem++){
@@ -106356,24 +110468,22 @@ SQLITE_PRIVATE ExprList *sqlcipher_sqlite3ExprListDup(sqlcipher_sqlite3 *db, Exp
&& pOldExpr->op==TK_SELECT_COLUMN
&& (pNewExpr = pItem->pExpr)!=0
){
- assert( pNewExpr->iColumn==0 || i>0 );
- if( pNewExpr->iColumn==0 ){
- assert( pOldExpr->pLeft==pOldExpr->pRight );
- pPriorSelectCol = pNewExpr->pLeft = pNewExpr->pRight;
+ if( pNewExpr->pRight ){
+ pPriorSelectColOld = pOldExpr->pRight;
+ pPriorSelectColNew = pNewExpr->pRight;
+ pNewExpr->pLeft = pNewExpr->pRight;
}else{
- assert( i>0 );
- assert( pItem[-1].pExpr!=0 );
- assert( pNewExpr->iColumn==pItem[-1].pExpr->iColumn+1 );
- assert( pPriorSelectCol==pItem[-1].pExpr->pLeft );
- pNewExpr->pLeft = pPriorSelectCol;
+ if( pOldExpr->pLeft!=pPriorSelectColOld ){
+ pPriorSelectColOld = pOldExpr->pLeft;
+ pPriorSelectColNew = sqlcipher_sqlite3ExprDup(db, pPriorSelectColOld, flags);
+ pNewExpr->pRight = pPriorSelectColNew;
+ }
+ pNewExpr->pLeft = pPriorSelectColNew;
}
}
pItem->zEName = sqlcipher_sqlite3DbStrDup(db, pOldItem->zEName);
- pItem->sortFlags = pOldItem->sortFlags;
- pItem->eEName = pOldItem->eEName;
- pItem->done = 0;
- pItem->bNulls = pOldItem->bNulls;
- pItem->bSorterRef = pOldItem->bSorterRef;
+ pItem->fg = pOldItem->fg;
+ pItem->fg.done = 0;
pItem->u = pOldItem->u;
}
return pNew;
@@ -106387,7 +110497,7 @@ SQLITE_PRIVATE ExprList *sqlcipher_sqlite3ExprListDup(sqlcipher_sqlite3 *db, Exp
*/
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) \
|| !defined(SQLITE_OMIT_SUBQUERY)
-SQLITE_PRIVATE SrcList *sqlcipher_sqlite3SrcListDup(sqlcipher_sqlite3 *db, SrcList *p, int flags){
+SQLITE_PRIVATE SrcList *sqlcipher_sqlite3SrcListDup(sqlcipher_sqlite3 *db, const SrcList *p, int flags){
SrcList *pNew;
int i;
int nByte;
@@ -106398,8 +110508,8 @@ SQLITE_PRIVATE SrcList *sqlcipher_sqlite3SrcListDup(sqlcipher_sqlite3 *db, SrcLi
if( pNew==0 ) return 0;
pNew->nSrc = pNew->nAlloc = p->nSrc;
for(i=0; i<p->nSrc; i++){
- struct SrcList_item *pNewItem = &pNew->a[i];
- struct SrcList_item *pOldItem = &p->a[i];
+ SrcItem *pNewItem = &pNew->a[i];
+ const SrcItem *pOldItem = &p->a[i];
Table *pTab;
pNewItem->pSchema = pOldItem->pSchema;
pNewItem->zDatabase = sqlcipher_sqlite3DbStrDup(db, pOldItem->zDatabase);
@@ -106412,7 +110522,10 @@ SQLITE_PRIVATE SrcList *sqlcipher_sqlite3SrcListDup(sqlcipher_sqlite3 *db, SrcLi
if( pNewItem->fg.isIndexedBy ){
pNewItem->u1.zIndexedBy = sqlcipher_sqlite3DbStrDup(db, pOldItem->u1.zIndexedBy);
}
- pNewItem->pIBIndex = pOldItem->pIBIndex;
+ pNewItem->u2 = pOldItem->u2;
+ if( pNewItem->fg.isCte ){
+ pNewItem->u2.pCteUse->nUse++;
+ }
if( pNewItem->fg.isTabFunc ){
pNewItem->u1.pFuncArg =
sqlcipher_sqlite3ExprListDup(db, pOldItem->u1.pFuncArg, flags);
@@ -106422,41 +110535,39 @@ SQLITE_PRIVATE SrcList *sqlcipher_sqlite3SrcListDup(sqlcipher_sqlite3 *db, SrcLi
pTab->nTabRef++;
}
pNewItem->pSelect = sqlcipher_sqlite3SelectDup(db, pOldItem->pSelect, flags);
- pNewItem->pOn = sqlcipher_sqlite3ExprDup(db, pOldItem->pOn, flags);
- pNewItem->pUsing = sqlcipher_sqlite3IdListDup(db, pOldItem->pUsing);
+ if( pOldItem->fg.isUsing ){
+ assert( pNewItem->fg.isUsing );
+ pNewItem->u3.pUsing = sqlcipher_sqlite3IdListDup(db, pOldItem->u3.pUsing);
+ }else{
+ pNewItem->u3.pOn = sqlcipher_sqlite3ExprDup(db, pOldItem->u3.pOn, flags);
+ }
pNewItem->colUsed = pOldItem->colUsed;
}
return pNew;
}
-SQLITE_PRIVATE IdList *sqlcipher_sqlite3IdListDup(sqlcipher_sqlite3 *db, IdList *p){
+SQLITE_PRIVATE IdList *sqlcipher_sqlite3IdListDup(sqlcipher_sqlite3 *db, const IdList *p){
IdList *pNew;
int i;
assert( db!=0 );
if( p==0 ) return 0;
- pNew = sqlcipher_sqlite3DbMallocRawNN(db, sizeof(*pNew) );
+ assert( p->eU4!=EU4_EXPR );
+ pNew = sqlcipher_sqlite3DbMallocRawNN(db, sizeof(*pNew)+(p->nId-1)*sizeof(p->a[0]) );
if( pNew==0 ) return 0;
pNew->nId = p->nId;
- pNew->a = sqlcipher_sqlite3DbMallocRawNN(db, p->nId*sizeof(p->a[0]) );
- if( pNew->a==0 ){
- sqlcipher_sqlite3DbFreeNN(db, pNew);
- return 0;
- }
- /* Note that because the size of the allocation for p->a[] is not
- ** necessarily a power of two, sqlcipher_sqlite3IdListAppend() may not be called
- ** on the duplicate created by this function. */
+ pNew->eU4 = p->eU4;
for(i=0; i<p->nId; i++){
struct IdList_item *pNewItem = &pNew->a[i];
- struct IdList_item *pOldItem = &p->a[i];
+ const struct IdList_item *pOldItem = &p->a[i];
pNewItem->zName = sqlcipher_sqlite3DbStrDup(db, pOldItem->zName);
- pNewItem->idx = pOldItem->idx;
+ pNewItem->u4 = pOldItem->u4;
}
return pNew;
}
-SQLITE_PRIVATE Select *sqlcipher_sqlite3SelectDup(sqlcipher_sqlite3 *db, Select *pDup, int flags){
+SQLITE_PRIVATE Select *sqlcipher_sqlite3SelectDup(sqlcipher_sqlite3 *db, const Select *pDup, int flags){
Select *pRet = 0;
Select *pNext = 0;
Select **pp = &pRet;
- Select *p;
+ const Select *p;
assert( db!=0 );
for(p=pDup; p; p=p->pPrior){
@@ -106478,13 +110589,21 @@ SQLITE_PRIVATE Select *sqlcipher_sqlite3SelectDup(sqlcipher_sqlite3 *db, Select
pNew->addrOpenEphm[0] = -1;
pNew->addrOpenEphm[1] = -1;
pNew->nSelectRow = p->nSelectRow;
- pNew->pWith = withDup(db, p->pWith);
+ pNew->pWith = sqlcipher_sqlite3WithDup(db, p->pWith);
#ifndef SQLITE_OMIT_WINDOWFUNC
pNew->pWin = 0;
pNew->pWinDefn = sqlcipher_sqlite3WindowListDup(db, p->pWinDefn);
if( p->pWin && db->mallocFailed==0 ) gatherSelectWindows(pNew);
#endif
pNew->selId = p->selId;
+ if( db->mallocFailed ){
+ /* Any prior OOM might have left the Select object incomplete.
+ ** Delete the whole thing rather than allow an incomplete Select
+ ** to be used by the code generator. */
+ pNew->pNext = 0;
+ sqlcipher_sqlite3SelectDelete(db, pNew);
+ break;
+ }
*pp = pNew;
pp = &pNew->pPrior;
pNext = pNew;
@@ -106493,7 +110612,7 @@ SQLITE_PRIVATE Select *sqlcipher_sqlite3SelectDup(sqlcipher_sqlite3 *db, Select
return pRet;
}
#else
-SQLITE_PRIVATE Select *sqlcipher_sqlite3SelectDup(sqlcipher_sqlite3 *db, Select *p, int flags){
+SQLITE_PRIVATE Select *sqlcipher_sqlite3SelectDup(sqlcipher_sqlite3 *db, const Select *p, int flags){
assert( p==0 );
return 0;
}
@@ -106515,41 +110634,64 @@ SQLITE_PRIVATE Select *sqlcipher_sqlite3SelectDup(sqlcipher_sqlite3 *db, Select
** NULL is returned. If non-NULL is returned, then it is guaranteed
** that the new entry was successfully appended.
*/
+static const struct ExprList_item zeroItem = {0};
+SQLITE_PRIVATE SQLITE_NOINLINE ExprList *sqlcipher_sqlite3ExprListAppendNew(
+ sqlcipher_sqlite3 *db, /* Database handle. Used for memory allocation */
+ Expr *pExpr /* Expression to be appended. Might be NULL */
+){
+ struct ExprList_item *pItem;
+ ExprList *pList;
+
+ pList = sqlcipher_sqlite3DbMallocRawNN(db, sizeof(ExprList)+sizeof(pList->a[0])*4 );
+ if( pList==0 ){
+ sqlcipher_sqlite3ExprDelete(db, pExpr);
+ return 0;
+ }
+ pList->nAlloc = 4;
+ pList->nExpr = 1;
+ pItem = &pList->a[0];
+ *pItem = zeroItem;
+ pItem->pExpr = pExpr;
+ return pList;
+}
+SQLITE_PRIVATE SQLITE_NOINLINE ExprList *sqlcipher_sqlite3ExprListAppendGrow(
+ sqlcipher_sqlite3 *db, /* Database handle. Used for memory allocation */
+ ExprList *pList, /* List to which to append. Might be NULL */
+ Expr *pExpr /* Expression to be appended. Might be NULL */
+){
+ struct ExprList_item *pItem;
+ ExprList *pNew;
+ pList->nAlloc *= 2;
+ pNew = sqlcipher_sqlite3DbRealloc(db, pList,
+ sizeof(*pList)+(pList->nAlloc-1)*sizeof(pList->a[0]));
+ if( pNew==0 ){
+ sqlcipher_sqlite3ExprListDelete(db, pList);
+ sqlcipher_sqlite3ExprDelete(db, pExpr);
+ return 0;
+ }else{
+ pList = pNew;
+ }
+ pItem = &pList->a[pList->nExpr++];
+ *pItem = zeroItem;
+ pItem->pExpr = pExpr;
+ return pList;
+}
SQLITE_PRIVATE ExprList *sqlcipher_sqlite3ExprListAppend(
Parse *pParse, /* Parsing context */
ExprList *pList, /* List to which to append. Might be NULL */
Expr *pExpr /* Expression to be appended. Might be NULL */
){
struct ExprList_item *pItem;
- sqlcipher_sqlite3 *db = pParse->db;
- assert( db!=0 );
if( pList==0 ){
- pList = sqlcipher_sqlite3DbMallocRawNN(db, sizeof(ExprList) );
- if( pList==0 ){
- goto no_mem;
- }
- pList->nExpr = 0;
- }else if( (pList->nExpr & (pList->nExpr-1))==0 ){
- ExprList *pNew;
- pNew = sqlcipher_sqlite3DbRealloc(db, pList,
- sizeof(*pList)+(2*(sqlcipher_sqlite3_int64)pList->nExpr-1)*sizeof(pList->a[0]));
- if( pNew==0 ){
- goto no_mem;
- }
- pList = pNew;
+ return sqlcipher_sqlite3ExprListAppendNew(pParse->db,pExpr);
+ }
+ if( pList->nAlloc<pList->nExpr+1 ){
+ return sqlcipher_sqlite3ExprListAppendGrow(pParse->db,pList,pExpr);
}
pItem = &pList->a[pList->nExpr++];
- assert( offsetof(struct ExprList_item,zEName)==sizeof(pItem->pExpr) );
- assert( offsetof(struct ExprList_item,pExpr)==0 );
- memset(&pItem->zEName,0,sizeof(*pItem)-offsetof(struct ExprList_item,zEName));
+ *pItem = zeroItem;
pItem->pExpr = pExpr;
return pList;
-
-no_mem:
- /* Avoid leaking memory if malloc has failed. */
- sqlcipher_sqlite3ExprDelete(db, pExpr);
- sqlcipher_sqlite3ExprListDelete(db, pList);
- return 0;
}
/*
@@ -106590,11 +110732,9 @@ SQLITE_PRIVATE ExprList *sqlcipher_sqlite3ExprListAppendVector(
}
for(i=0; i<pColumns->nId; i++){
- Expr *pSubExpr = sqlcipher_sqlite3ExprForVectorField(pParse, pExpr, i);
+ Expr *pSubExpr = sqlcipher_sqlite3ExprForVectorField(pParse, pExpr, i, pColumns->nId);
assert( pSubExpr!=0 || db->mallocFailed );
- assert( pSubExpr==0 || pSubExpr->iTable==0 );
if( pSubExpr==0 ) continue;
- pSubExpr->iTable = pColumns->nId;
pList = sqlcipher_sqlite3ExprListAppend(pParse, pList, pSubExpr);
if( pList ){
assert( pList->nExpr==iFirst+i+1 );
@@ -106643,16 +110783,16 @@ SQLITE_PRIVATE void sqlcipher_sqlite3ExprListSetSortOrder(ExprList *p, int iSort
);
pItem = &p->a[p->nExpr-1];
- assert( pItem->bNulls==0 );
+ assert( pItem->fg.bNulls==0 );
if( iSortOrder==SQLITE_SO_UNDEFINED ){
iSortOrder = SQLITE_SO_ASC;
}
- pItem->sortFlags = (u8)iSortOrder;
+ pItem->fg.sortFlags = (u8)iSortOrder;
if( eNulls!=SQLITE_SO_UNDEFINED ){
- pItem->bNulls = 1;
+ pItem->fg.bNulls = 1;
if( iSortOrder!=eNulls ){
- pItem->sortFlags |= KEYINFO_ORDER_BIGNULL;
+ pItem->fg.sortFlags |= KEYINFO_ORDER_BIGNULL;
}
}
}
@@ -106668,7 +110808,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3ExprListSetSortOrder(ExprList *p, int iSort
SQLITE_PRIVATE void sqlcipher_sqlite3ExprListSetName(
Parse *pParse, /* Parsing context */
ExprList *pList, /* List to which to add the span. */
- Token *pName, /* Name to be added */
+ const Token *pName, /* Name to be added */
int dequote /* True to cause the name to be dequoted */
){
assert( pList!=0 || pParse->db->mallocFailed!=0 );
@@ -106678,7 +110818,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3ExprListSetName(
assert( pList->nExpr>0 );
pItem = &pList->a[pList->nExpr-1];
assert( pItem->zEName==0 );
- assert( pItem->eEName==ENAME_NAME );
+ assert( pItem->fg.eEName==ENAME_NAME );
pItem->zEName = sqlcipher_sqlite3DbStrNDup(pParse->db, pName->z, pName->n);
if( dequote ){
/* If dequote==0, then pName->z does not point to part of a DDL
@@ -106686,7 +110826,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3ExprListSetName(
** to the token-map. */
sqlcipher_sqlite3Dequote(pItem->zEName);
if( IN_RENAME_OBJECT ){
- sqlcipher_sqlite3RenameTokenMap(pParse, (void*)pItem->zEName, pName);
+ sqlcipher_sqlite3RenameTokenMap(pParse, (const void*)pItem->zEName, pName);
}
}
}
@@ -106713,7 +110853,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3ExprListSetSpan(
assert( pList->nExpr>0 );
if( pItem->zEName==0 ){
pItem->zEName = sqlcipher_sqlite3DbSpanDup(db, zStart, zEnd);
- pItem->eEName = ENAME_SPAN;
+ pItem->fg.eEName = ENAME_SPAN;
}
}
}
@@ -106805,7 +110945,7 @@ SQLITE_PRIVATE u32 sqlcipher_sqlite3IsTrueOrFalse(const char *zIn){
SQLITE_PRIVATE int sqlcipher_sqlite3ExprIdToTrueFalse(Expr *pExpr){
u32 v;
assert( pExpr->op==TK_ID || pExpr->op==TK_STRING );
- if( !ExprHasProperty(pExpr, EP_Quoted)
+ if( !ExprHasProperty(pExpr, EP_Quoted|EP_IntValue)
&& (v = sqlcipher_sqlite3IsTrueOrFalse(pExpr->u.zToken))!=0
){
pExpr->op = TK_TRUEFALSE;
@@ -106822,6 +110962,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ExprIdToTrueFalse(Expr *pExpr){
SQLITE_PRIVATE int sqlcipher_sqlite3ExprTruthValue(const Expr *pExpr){
pExpr = sqlcipher_sqlite3ExprSkipCollate((Expr*)pExpr);
assert( pExpr->op==TK_TRUEFALSE );
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
assert( sqlcipher_sqlite3StrICmp(pExpr->u.zToken,"true")==0
|| sqlcipher_sqlite3StrICmp(pExpr->u.zToken,"false")==0 );
return pExpr->u.zToken[4]==0;
@@ -106884,9 +111025,9 @@ SQLITE_PRIVATE Expr *sqlcipher_sqlite3ExprSimplifiedAndOr(Expr *pExpr){
static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
/* If pWalker->eCode is 2 then any term of the expression that comes from
- ** the ON or USING clauses of a left join disqualifies the expression
+ ** the ON or USING clauses of an outer join disqualifies the expression
** from being considered constant. */
- if( pWalker->eCode==2 && ExprHasProperty(pExpr, EP_FromJoin) ){
+ if( pWalker->eCode==2 && ExprHasProperty(pExpr, EP_OuterON) ){
pWalker->eCode = 0;
return WRC_Abort;
}
@@ -107005,6 +111146,42 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ExprIsTableConstant(Expr *p, int iCur){
return exprIsConst(p, 3, iCur);
}
+/*
+** Check pExpr to see if it is an invariant constraint on data source pSrc.
+** This is an optimization. False negatives will perhaps cause slower
+** queries, but false positives will yield incorrect answers. So when in
+** doubt, return 0.
+**
+** To be an invariant constraint, the following must be true:
+**
+** (1) pExpr cannot refer to any table other than pSrc->iCursor.
+**
+** (2) pExpr cannot use subqueries or non-deterministic functions.
+**
+** (3) pSrc cannot be part of the left operand for a RIGHT JOIN.
+** (Is there some way to relax this constraint?)
+**
+** (4) If pSrc is the right operand of a LEFT JOIN, then...
+** (4a) pExpr must come from an ON clause..
+ (4b) and specifically the ON clause associated with the LEFT JOIN.
+**
+** (5) If pSrc is not the right operand of a LEFT JOIN or the left
+** operand of a RIGHT JOIN, then pExpr must be from the WHERE
+** clause, not an ON clause.
+*/
+SQLITE_PRIVATE int sqlcipher_sqlite3ExprIsTableConstraint(Expr *pExpr, const SrcItem *pSrc){
+ if( pSrc->fg.jointype & JT_LTORJ ){
+ return 0; /* rule (3) */
+ }
+ if( pSrc->fg.jointype & JT_LEFT ){
+ if( !ExprHasProperty(pExpr, EP_OuterON) ) return 0; /* rule (4a) */
+ if( pExpr->w.iJoin!=pSrc->iCursor ) return 0; /* rule (4b) */
+ }else{
+ if( ExprHasProperty(pExpr, EP_OuterON) ) return 0; /* rule (5) */
+ }
+ return sqlcipher_sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor); /* rules (1), (2) */
+}
+
/*
** sqlcipher_sqlite3WalkExpr() callback used by sqlcipher_sqlite3ExprIsConstantOrGroupBy().
@@ -107026,7 +111203,7 @@ static int exprNodeIsConstantOrGroupBy(Walker *pWalker, Expr *pExpr){
}
/* Check if pExpr is a sub-select. If so, consider it variable. */
- if( ExprHasProperty(pExpr, EP_xIsSelect) ){
+ if( ExprUseXSelect(pExpr) ){
pWalker->eCode = 0;
return WRC_Abort;
}
@@ -107114,7 +111291,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ExprContainsSubquery(Expr *p){
** in *pValue. If the expression is not an integer or if it is too big
** to fit in a signed 32-bit integer, return 0 and leave *pValue unchanged.
*/
-SQLITE_PRIVATE int sqlcipher_sqlite3ExprIsInteger(Expr *p, int *pValue){
+SQLITE_PRIVATE int sqlcipher_sqlite3ExprIsInteger(const Expr *p, int *pValue){
int rc = 0;
if( NEVER(p==0) ) return 0; /* Used to only happen following on OOM */
@@ -107133,9 +111310,9 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ExprIsInteger(Expr *p, int *pValue){
break;
}
case TK_UMINUS: {
- int v;
+ int v = 0;
if( sqlcipher_sqlite3ExprIsInteger(p->pLeft, &v) ){
- assert( v!=(-2147483647-1) );
+ assert( ((unsigned int)v)!=0x80000000 );
*pValue = -v;
rc = 1;
}
@@ -107162,8 +111339,10 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ExprIsInteger(Expr *p, int *pValue){
*/
SQLITE_PRIVATE int sqlcipher_sqlite3ExprCanBeNull(const Expr *p){
u8 op;
+ assert( p!=0 );
while( p->op==TK_UPLUS || p->op==TK_UMINUS ){
p = p->pLeft;
+ assert( p!=0 );
}
op = p->op;
if( op==TK_REGISTER ) op = p->op2;
@@ -107174,10 +111353,11 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ExprCanBeNull(const Expr *p){
case TK_BLOB:
return 0;
case TK_COLUMN:
+ assert( ExprUseYTab(p) );
return ExprHasProperty(p, EP_CanBeNull) ||
p->y.pTab==0 || /* Reference to column of index on expression */
(p->iColumn>=0
- && ALWAYS(p->y.pTab->aCol!=0) /* Defense against OOM problems */
+ && p->y.pTab->aCol!=0 /* Possible due to prior error */
&& p->y.pTab->aCol[p->iColumn].notNull==0);
default:
return 1;
@@ -107245,13 +111425,13 @@ SQLITE_PRIVATE int sqlcipher_sqlite3IsRowid(const char *z){
** table, then return NULL.
*/
#ifndef SQLITE_OMIT_SUBQUERY
-static Select *isCandidateForInOpt(Expr *pX){
+static Select *isCandidateForInOpt(const Expr *pX){
Select *p;
SrcList *pSrc;
ExprList *pEList;
Table *pTab;
int i;
- if( !ExprHasProperty(pX, EP_xIsSelect) ) return 0; /* Not a subquery */
+ if( !ExprUseXSelect(pX) ) return 0; /* Not a subquery */
if( ExprHasProperty(pX, EP_VarSelect) ) return 0; /* Correlated subq */
p = pX->x.pSelect;
if( p->pPrior ) return 0; /* Not a compound SELECT */
@@ -107269,7 +111449,7 @@ static Select *isCandidateForInOpt(Expr *pX){
if( pSrc->a[0].pSelect ) return 0; /* FROM is not a subquery or view */
pTab = pSrc->a[0].pTab;
assert( pTab!=0 );
- assert( pTab->pSelect==0 ); /* FROM clause is not a view */
+ assert( !IsView(pTab) ); /* FROM clause is not a view */
if( IsVirtual(pTab) ) return 0; /* FROM clause not a virtual table */
pEList = p->pEList;
assert( pEList!=0 );
@@ -107329,7 +111509,7 @@ static int sqlcipher_sqlite3InRhsIsConstant(Expr *pIn){
** all members of the RHS set, skipping duplicates.
**
** 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.
+** and the *piTab parameter is set to the index of that cursor.
**
** The returned value of this function indicates the b-tree type, as follows:
**
@@ -107349,7 +111529,10 @@ static int sqlcipher_sqlite3InRhsIsConstant(Expr *pIn){
** 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 ephemeral table instead of an
-** existing table.
+** existing table. In this case, the creation and initialization of the
+** ephmeral table might be put inside of a subroutine, the EP_Subrtn flag
+** will be set on pX and the pX->y.sub fields will be set to show where
+** the subroutine is coded.
**
** The inFlags parameter must contain, at a minimum, one of the bits
** IN_INDEX_MEMBERSHIP or IN_INDEX_LOOP but not both. If inFlags contains
@@ -107410,19 +111593,20 @@ SQLITE_PRIVATE int sqlcipher_sqlite3FindInIndex(
){
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 iTab; /* Cursor of the RHS table */
int mustBeUnique; /* True if RHS must be unique */
Vdbe *v = sqlcipher_sqlite3GetVdbe(pParse); /* Virtual machine being coded */
assert( pX->op==TK_IN );
mustBeUnique = (inFlags & IN_INDEX_LOOP)!=0;
+ iTab = pParse->nTab++;
/* If the RHS of this IN(...) operator is a SELECT, and if it matters
** whether or not the SELECT result contains NULL values, check whether
** or not NULL is actually possible (it may not be, for example, due
** to NOT NULL constraints in the schema). If no NULL values are possible,
** set prRhsHasNull to 0 before continuing. */
- if( prRhsHasNull && (pX->flags & EP_xIsSelect) ){
+ if( prRhsHasNull && ExprUseXSelect(pX) ){
int i;
ExprList *pEList = pX->x.pSelect->pEList;
for(i=0; i<pEList->nExpr; i++){
@@ -107450,7 +111634,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3FindInIndex(
/* Code an OP_Transaction and OP_TableLock for <table>. */
iDb = sqlcipher_sqlite3SchemaToIndex(db, pTab->pSchema);
- assert( iDb>=0 && iDb<SQLITE_MAX_ATTACHED );
+ assert( iDb>=0 && iDb<SQLITE_MAX_DB );
sqlcipher_sqlite3CodeVerifySchema(pParse, iDb);
sqlcipher_sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
@@ -107578,9 +111762,11 @@ SQLITE_PRIVATE int sqlcipher_sqlite3FindInIndex(
*/
if( eType==0
&& (inFlags & IN_INDEX_NOOP_OK)
- && !ExprHasProperty(pX, EP_xIsSelect)
+ && ExprUseXList(pX)
&& (!sqlcipher_sqlite3InRhsIsConstant(pX) || pX->x.pList->nExpr<=2)
){
+ pParse->nTab--; /* Back out the allocation of the unused cursor */
+ iTab = -1; /* Cursor is not allocated */
eType = IN_INDEX_NOOP;
}
@@ -107623,10 +111809,10 @@ SQLITE_PRIVATE int sqlcipher_sqlite3FindInIndex(
** It is the responsibility of the caller to ensure that the returned
** string is eventually freed using sqlcipher_sqlite3DbFree().
*/
-static char *exprINAffinity(Parse *pParse, Expr *pExpr){
+static char *exprINAffinity(Parse *pParse, const Expr *pExpr){
Expr *pLeft = pExpr->pLeft;
int nVal = sqlcipher_sqlite3ExprVectorSize(pLeft);
- Select *pSelect = (pExpr->flags & EP_xIsSelect) ? pExpr->x.pSelect : 0;
+ Select *pSelect = ExprUseXSelect(pExpr) ? pExpr->x.pSelect : 0;
char *zRet;
assert( pExpr->op==TK_IN );
@@ -107676,7 +111862,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3SubselectError(Parse *pParse, int nActual,
*/
SQLITE_PRIVATE void sqlcipher_sqlite3VectorErrorMsg(Parse *pParse, Expr *pExpr){
#ifndef SQLITE_OMIT_SUBQUERY
- if( pExpr->flags & EP_xIsSelect ){
+ if( ExprUseXSelect(pExpr) ){
sqlcipher_sqlite3SubselectError(pParse, pExpr->x.pSelect->pEList->nExpr, 1);
}else
#endif
@@ -107740,24 +111926,26 @@ SQLITE_PRIVATE void sqlcipher_sqlite3CodeRhsOfIN(
*/
if( ExprHasProperty(pExpr, EP_Subrtn) ){
addrOnce = sqlcipher_sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
- if( ExprHasProperty(pExpr, EP_xIsSelect) ){
+ if( ExprUseXSelect(pExpr) ){
ExplainQueryPlan((pParse, 0, "REUSE LIST SUBQUERY %d",
pExpr->x.pSelect->selId));
}
+ assert( ExprUseYSub(pExpr) );
sqlcipher_sqlite3VdbeAddOp2(v, OP_Gosub, pExpr->y.sub.regReturn,
pExpr->y.sub.iAddr);
+ assert( iTab!=pExpr->iTable );
sqlcipher_sqlite3VdbeAddOp2(v, OP_OpenDup, iTab, pExpr->iTable);
sqlcipher_sqlite3VdbeJumpHere(v, addrOnce);
return;
}
/* Begin coding the subroutine */
+ assert( !ExprUseYWin(pExpr) );
ExprSetProperty(pExpr, EP_Subrtn);
assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) );
pExpr->y.sub.regReturn = ++pParse->nMem;
pExpr->y.sub.iAddr =
- sqlcipher_sqlite3VdbeAddOp2(v, OP_Integer, 0, pExpr->y.sub.regReturn) + 1;
- VdbeComment((v, "return address"));
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_BeginSubrtn, 0, pExpr->y.sub.regReturn) + 1;
addrOnce = sqlcipher_sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
}
@@ -107772,7 +111960,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3CodeRhsOfIN(
pExpr->iTable = iTab;
addr = sqlcipher_sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pExpr->iTable, nVal);
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
- if( ExprHasProperty(pExpr, EP_xIsSelect) ){
+ if( ExprUseXSelect(pExpr) ){
VdbeComment((v, "Result of SELECT %u", pExpr->x.pSelect->selId));
}else{
VdbeComment((v, "RHS of IN operator"));
@@ -107780,7 +111968,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3CodeRhsOfIN(
#endif
pKeyInfo = sqlcipher_sqlite3KeyInfoAlloc(pParse->db, nVal, 1);
- if( ExprHasProperty(pExpr, EP_xIsSelect) ){
+ if( ExprUseXSelect(pExpr) ){
/* Case 1: expr IN (SELECT ...)
**
** Generate code to write the results of the select into the temporary
@@ -107795,19 +111983,23 @@ SQLITE_PRIVATE void sqlcipher_sqlite3CodeRhsOfIN(
/* If the LHS and RHS of the IN operator do not match, that
** error will have been caught long before we reach this point. */
if( ALWAYS(pEList->nExpr==nVal) ){
+ Select *pCopy;
SelectDest dest;
int i;
+ int rc;
sqlcipher_sqlite3SelectDestInit(&dest, SRT_Set, iTab);
dest.zAffSdst = exprINAffinity(pParse, pExpr);
pSelect->iLimit = 0;
testcase( pSelect->selFlags & SF_Distinct );
testcase( pKeyInfo==0 ); /* Caused by OOM in sqlcipher_sqlite3KeyInfoAlloc() */
- if( sqlcipher_sqlite3Select(pParse, pSelect, &dest) ){
- sqlcipher_sqlite3DbFree(pParse->db, dest.zAffSdst);
+ pCopy = sqlcipher_sqlite3SelectDup(pParse->db, pSelect, 0);
+ rc = pParse->db->mallocFailed ? 1 :sqlcipher_sqlite3Select(pParse, pCopy, &dest);
+ sqlcipher_sqlite3SelectDelete(pParse->db, pCopy);
+ sqlcipher_sqlite3DbFree(pParse->db, dest.zAffSdst);
+ if( rc ){
sqlcipher_sqlite3KeyInfoUnref(pKeyInfo);
return;
}
- sqlcipher_sqlite3DbFree(pParse->db, dest.zAffSdst);
assert( pKeyInfo!=0 ); /* OOM will cause exit after sqlcipher_sqlite3Select() */
assert( pEList!=0 );
assert( pEList->nExpr>0 );
@@ -107855,6 +112047,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3CodeRhsOfIN(
** expression we need to rerun this code each time.
*/
if( addrOnce && !sqlcipher_sqlite3ExprIsConstant(pE2) ){
+ sqlcipher_sqlite3VdbeChangeToNoop(v, addrOnce-1);
sqlcipher_sqlite3VdbeChangeToNoop(v, addrOnce);
ExprClearProperty(pExpr, EP_Subrtn);
addrOnce = 0;
@@ -107874,8 +112067,12 @@ SQLITE_PRIVATE void sqlcipher_sqlite3CodeRhsOfIN(
if( addrOnce ){
sqlcipher_sqlite3VdbeJumpHere(v, addrOnce);
/* Subroutine return */
- sqlcipher_sqlite3VdbeAddOp1(v, OP_Return, pExpr->y.sub.regReturn);
- sqlcipher_sqlite3VdbeChangeP1(v, pExpr->y.sub.iAddr-1, sqlcipher_sqlite3VdbeCurrentAddr(v)-1);
+ assert( ExprUseYSub(pExpr) );
+ assert( sqlcipher_sqlite3VdbeGetOp(v,pExpr->y.sub.iAddr-1)->opcode==OP_BeginSubrtn
+ || pParse->nErr );
+ sqlcipher_sqlite3VdbeAddOp3(v, OP_Return, pExpr->y.sub.regReturn,
+ pExpr->y.sub.iAddr, 1);
+ VdbeCoverage(v);
sqlcipher_sqlite3ClearTempRegCache(pParse);
}
}
@@ -107906,12 +112103,31 @@ SQLITE_PRIVATE int sqlcipher_sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
Vdbe *v = pParse->pVdbe;
assert( v!=0 );
+ if( pParse->nErr ) return 0;
testcase( pExpr->op==TK_EXISTS );
testcase( pExpr->op==TK_SELECT );
assert( pExpr->op==TK_EXISTS || pExpr->op==TK_SELECT );
- assert( ExprHasProperty(pExpr, EP_xIsSelect) );
+ assert( ExprUseXSelect(pExpr) );
pSel = pExpr->x.pSelect;
+ /* If this routine has already been coded, then invoke it as a
+ ** subroutine. */
+ if( ExprHasProperty(pExpr, EP_Subrtn) ){
+ ExplainQueryPlan((pParse, 0, "REUSE SUBQUERY %d", pSel->selId));
+ assert( ExprUseYSub(pExpr) );
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_Gosub, pExpr->y.sub.regReturn,
+ pExpr->y.sub.iAddr);
+ return pExpr->iTable;
+ }
+
+ /* Begin coding the subroutine */
+ assert( !ExprUseYWin(pExpr) );
+ assert( !ExprHasProperty(pExpr, EP_Reduced|EP_TokenOnly) );
+ ExprSetProperty(pExpr, EP_Subrtn);
+ pExpr->y.sub.regReturn = ++pParse->nMem;
+ pExpr->y.sub.iAddr =
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_BeginSubrtn, 0, pExpr->y.sub.regReturn) + 1;
+
/* The evaluation of the EXISTS/SELECT must be repeated every time it
** is encountered if any of the following is true:
**
@@ -107923,22 +112139,6 @@ SQLITE_PRIVATE int sqlcipher_sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
** save the results, and reuse the same result on subsequent invocations.
*/
if( !ExprHasProperty(pExpr, EP_VarSelect) ){
- /* If this routine has already been coded, then invoke it as a
- ** subroutine. */
- if( ExprHasProperty(pExpr, EP_Subrtn) ){
- ExplainQueryPlan((pParse, 0, "REUSE SUBQUERY %d", pSel->selId));
- sqlcipher_sqlite3VdbeAddOp2(v, OP_Gosub, pExpr->y.sub.regReturn,
- pExpr->y.sub.iAddr);
- return pExpr->iTable;
- }
-
- /* Begin coding the subroutine */
- ExprSetProperty(pExpr, EP_Subrtn);
- pExpr->y.sub.regReturn = ++pParse->nMem;
- pExpr->y.sub.iAddr =
- sqlcipher_sqlite3VdbeAddOp2(v, OP_Integer, 0, pExpr->y.sub.regReturn) + 1;
- VdbeComment((v, "return address"));
-
addrOnce = sqlcipher_sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
}
@@ -107987,19 +112187,24 @@ SQLITE_PRIVATE int sqlcipher_sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
}
pSel->iLimit = 0;
if( sqlcipher_sqlite3Select(pParse, pSel, &dest) ){
+ pExpr->op2 = pExpr->op;
+ pExpr->op = TK_ERROR;
return 0;
}
pExpr->iTable = rReg = dest.iSDParm;
ExprSetVVAProperty(pExpr, EP_NoReduce);
if( addrOnce ){
sqlcipher_sqlite3VdbeJumpHere(v, addrOnce);
-
- /* Subroutine return */
- sqlcipher_sqlite3VdbeAddOp1(v, OP_Return, pExpr->y.sub.regReturn);
- sqlcipher_sqlite3VdbeChangeP1(v, pExpr->y.sub.iAddr-1, sqlcipher_sqlite3VdbeCurrentAddr(v)-1);
- sqlcipher_sqlite3ClearTempRegCache(pParse);
}
+ /* Subroutine return */
+ assert( ExprUseYSub(pExpr) );
+ assert( sqlcipher_sqlite3VdbeGetOp(v,pExpr->y.sub.iAddr-1)->opcode==OP_BeginSubrtn
+ || pParse->nErr );
+ sqlcipher_sqlite3VdbeAddOp3(v, OP_Return, pExpr->y.sub.regReturn,
+ pExpr->y.sub.iAddr, 1);
+ VdbeCoverage(v);
+ sqlcipher_sqlite3ClearTempRegCache(pParse);
return rReg;
}
#endif /* SQLITE_OMIT_SUBQUERY */
@@ -108013,7 +112218,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
*/
SQLITE_PRIVATE int sqlcipher_sqlite3ExprCheckIN(Parse *pParse, Expr *pIn){
int nVector = sqlcipher_sqlite3ExprVectorSize(pIn->pLeft);
- if( (pIn->flags & EP_xIsSelect) ){
+ if( ExprUseXSelect(pIn) && !pParse->db->mallocFailed ){
if( nVector!=pIn->x.pSelect->pEList->nExpr ){
sqlcipher_sqlite3SubselectError(pParse, pIn->x.pSelect->pEList->nExpr, nVector);
return 1;
@@ -108147,13 +112352,15 @@ static void sqlcipher_sqlite3ExprCodeIN(
** This is step (1) in the in-operator.md optimized algorithm.
*/
if( eType==IN_INDEX_NOOP ){
- ExprList *pList = pExpr->x.pList;
- CollSeq *pColl = sqlcipher_sqlite3ExprCollSeq(pParse, pExpr->pLeft);
+ ExprList *pList;
+ CollSeq *pColl;
int labelOk = sqlcipher_sqlite3VdbeMakeLabel(pParse);
int r2, regToFree;
int regCkNull = 0;
int ii;
- assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
+ assert( ExprUseXList(pExpr) );
+ pList = pExpr->x.pList;
+ pColl = sqlcipher_sqlite3ExprCollSeq(pParse, pExpr->pLeft);
if( destIfNull!=destIfFalse ){
regCkNull = sqlcipher_sqlite3GetTempReg(pParse);
sqlcipher_sqlite3VdbeAddOp3(v, OP_BitAnd, rLhs, rLhs, regCkNull);
@@ -108201,9 +112408,9 @@ static void sqlcipher_sqlite3ExprCodeIN(
}else{
destStep2 = destStep6 = sqlcipher_sqlite3VdbeMakeLabel(pParse);
}
- if( pParse->nErr ) goto sqlcipher_sqlite3ExprCodeIN_finished;
for(i=0; i<nVector; i++){
Expr *p = sqlcipher_sqlite3VectorFieldSubexpr(pExpr->pLeft, i);
+ if( pParse->nErr ) goto sqlcipher_sqlite3ExprCodeIN_oom_error;
if( sqlcipher_sqlite3ExprCanBeNull(p) ){
sqlcipher_sqlite3VdbeAddOp2(v, OP_IsNull, rLhs+i, destStep2);
VdbeCoverage(v);
@@ -108341,11 +112548,12 @@ static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){
c = sqlcipher_sqlite3DecOrHexToI64(z, &value);
if( (c==3 && !negFlag) || (c==2) || (negFlag && value==SMALLEST_INT64)){
#ifdef SQLITE_OMIT_FLOATING_POINT
- sqlcipher_sqlite3ErrorMsg(pParse, "oversized integer: %s%s", negFlag ? "-" : "", z);
+ sqlcipher_sqlite3ErrorMsg(pParse, "oversized integer: %s%#T", negFlag?"-":"",pExpr);
#else
#ifndef SQLITE_OMIT_HEX_INTEGER
if( sqlcipher_sqlite3_strnicmp(z,"0x",2)==0 ){
- sqlcipher_sqlite3ErrorMsg(pParse, "hex literal too big: %s%s", negFlag?"-":"",z);
+ sqlcipher_sqlite3ErrorMsg(pParse, "hex literal too big: %s%#T",
+ negFlag?"-":"",pExpr);
}else
#endif
{
@@ -108389,9 +112597,10 @@ SQLITE_PRIVATE void sqlcipher_sqlite3ExprCodeLoadIndexColumn(
** and store the result in register regOut
*/
SQLITE_PRIVATE void sqlcipher_sqlite3ExprCodeGeneratedColumn(
- Parse *pParse,
- Column *pCol,
- int regOut
+ Parse *pParse, /* Parsing context */
+ Table *pTab, /* Table containing the generated column */
+ Column *pCol, /* The generated column */
+ int regOut /* Put the result in this register */
){
int iAddr;
Vdbe *v = pParse->pVdbe;
@@ -108402,7 +112611,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3ExprCodeGeneratedColumn(
}else{
iAddr = 0;
}
- sqlcipher_sqlite3ExprCodeCopy(pParse, pCol->pDflt, regOut);
+ sqlcipher_sqlite3ExprCodeCopy(pParse, sqlcipher_sqlite3ColumnExpr(pTab,pCol), regOut);
if( pCol->affinity>=SQLITE_AFF_TEXT ){
sqlcipher_sqlite3VdbeAddOp4(v, OP_Affinity, regOut, 1, 0, &pCol->affinity, 1);
}
@@ -108428,6 +112637,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3ExprCodeGetColumnOfTable(
}
if( iCol<0 || iCol==pTab->iPKey ){
sqlcipher_sqlite3VdbeAddOp2(v, OP_Rowid, iTabCur, regOut);
+ VdbeComment((v, "%s.rowid", pTab->zName));
}else{
int op;
int x;
@@ -108438,12 +112648,13 @@ SQLITE_PRIVATE void sqlcipher_sqlite3ExprCodeGetColumnOfTable(
}else if( (pCol = &pTab->aCol[iCol])->colFlags & COLFLAG_VIRTUAL ){
Parse *pParse = sqlcipher_sqlite3VdbeParser(v);
if( pCol->colFlags & COLFLAG_BUSY ){
- sqlcipher_sqlite3ErrorMsg(pParse, "generated column loop on \"%s\"", pCol->zName);
+ sqlcipher_sqlite3ErrorMsg(pParse, "generated column loop on \"%s\"",
+ pCol->zCnName);
}else{
int savedSelfTab = pParse->iSelfTab;
pCol->colFlags |= COLFLAG_BUSY;
pParse->iSelfTab = iTabCur+1;
- sqlcipher_sqlite3ExprCodeGeneratedColumn(pParse, pCol, regOut);
+ sqlcipher_sqlite3ExprCodeGeneratedColumn(pParse, pTab, pCol, regOut);
pParse->iSelfTab = savedSelfTab;
pCol->colFlags &= ~COLFLAG_BUSY;
}
@@ -108536,6 +112747,7 @@ static int exprCodeVector(Parse *pParse, Expr *p, int *piFreeable){
int i;
iResult = pParse->nMem+1;
pParse->nMem += nResult;
+ assert( ExprUseXList(p) );
for(i=0; i<nResult; i++){
sqlcipher_sqlite3ExprCodeFactorable(pParse, p->x.pList->a[i].pExpr, i+iResult);
}
@@ -108596,7 +112808,17 @@ static int exprCodeInlineFunction(
caseExpr.x.pList = pFarg;
return sqlcipher_sqlite3ExprCodeTarget(pParse, &caseExpr, target);
}
-
+#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
+ case INLINEFUNC_sqlite_offset: {
+ Expr *pArg = pFarg->a[0].pExpr;
+ if( pArg->op==TK_COLUMN && pArg->iTable>=0 ){
+ sqlcipher_sqlite3VdbeAddOp3(v, OP_Offset, pArg->iTable, pArg->iColumn, target);
+ }else{
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_Null, 0, target);
+ }
+ break;
+ }
+#endif
default: {
/* The UNLIKELY() function is a no-op. The result is the value
** of the first argument.
@@ -108610,6 +112832,7 @@ static int exprCodeInlineFunction(
** Test-only SQL functions that are only usable if enabled
** via SQLITE_TESTCTRL_INTERNAL_FUNCTIONS
*/
+#if !defined(SQLITE_UNTESTABLE)
case INLINEFUNC_expr_compare: {
/* Compare two expressions using sqlcipher_sqlite3ExprCompare() */
assert( nFarg==2 );
@@ -108643,7 +112866,6 @@ static int exprCodeInlineFunction(
break;
}
-#ifdef SQLITE_DEBUG
case INLINEFUNC_affinity: {
/* The AFFINITY() function evaluates to a string that describes
** the type affinity of the argument. This is used for testing of
@@ -108657,7 +112879,7 @@ static int exprCodeInlineFunction(
(aff<=SQLITE_AFF_NONE) ? "none" : azAff[aff-SQLITE_AFF_BLOB]);
break;
}
-#endif
+#endif /* !defined(SQLITE_UNTESTABLE) */
}
return target;
}
@@ -108711,7 +112933,8 @@ expr_code_doover:
if( pCol->iColumn<0 ){
VdbeComment((v,"%s.rowid",pTab->zName));
}else{
- VdbeComment((v,"%s.%s",pTab->zName,pTab->aCol[pCol->iColumn].zName));
+ VdbeComment((v,"%s.%s",
+ pTab->zName, pTab->aCol[pCol->iColumn].zCnName));
if( pTab->aCol[pCol->iColumn].affinity==SQLITE_AFF_REAL ){
sqlcipher_sqlite3VdbeAddOp1(v, OP_RealAffinity, target);
}
@@ -108733,6 +112956,7 @@ expr_code_doover:
*/
int aff;
iReg = sqlcipher_sqlite3ExprCodeTarget(pParse, pExpr->pLeft,target);
+ assert( ExprUseYTab(pExpr) );
if( pExpr->y.pTab ){
aff = sqlcipher_sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
}else{
@@ -108756,9 +112980,11 @@ expr_code_doover:
** immediately prior to the first column.
*/
Column *pCol;
- Table *pTab = pExpr->y.pTab;
+ Table *pTab;
int iSrc;
int iCol = pExpr->iColumn;
+ assert( ExprUseYTab(pExpr) );
+ pTab = pExpr->y.pTab;
assert( pTab!=0 );
assert( iCol>=XN_ROWID );
assert( iCol<pTab->nCol );
@@ -108772,12 +112998,12 @@ expr_code_doover:
if( pCol->colFlags & COLFLAG_GENERATED ){
if( pCol->colFlags & COLFLAG_BUSY ){
sqlcipher_sqlite3ErrorMsg(pParse, "generated column loop on \"%s\"",
- pCol->zName);
+ pCol->zCnName);
return 0;
}
pCol->colFlags |= COLFLAG_BUSY;
if( pCol->colFlags & COLFLAG_NOTAVAIL ){
- sqlcipher_sqlite3ExprCodeGeneratedColumn(pParse, pCol, iSrc);
+ sqlcipher_sqlite3ExprCodeGeneratedColumn(pParse, pTab, pCol, iSrc);
}
pCol->colFlags &= ~(COLFLAG_BUSY|COLFLAG_NOTAVAIL);
return iSrc;
@@ -108796,6 +113022,7 @@ expr_code_doover:
iTab = pParse->iSelfTab - 1;
}
}
+ assert( ExprUseYTab(pExpr) );
iReg = sqlcipher_sqlite3ExprCodeGetColumn(pParse, pExpr->y.pTab,
pExpr->iColumn, iTab, target,
pExpr->op2);
@@ -108829,7 +113056,7 @@ expr_code_doover:
** Expr node to be passed into this function, it will be handled
** sanely and not crash. But keep the assert() to bring the problem
** to the attention of the developers. */
- assert( op==TK_NULL );
+ assert( op==TK_NULL || op==TK_ERROR || pParse->db->mallocFailed );
sqlcipher_sqlite3VdbeAddOp2(v, OP_Null, 0, target);
return target;
}
@@ -108873,6 +113100,7 @@ expr_code_doover:
sqlcipher_sqlite3VdbeAddOp2(v, OP_SCopy, inReg, target);
inReg = target;
}
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
sqlcipher_sqlite3VdbeAddOp2(v, OP_Cast, target,
sqlcipher_sqlite3AffinityType(pExpr->u.zToken, 0));
return inReg;
@@ -108895,8 +113123,9 @@ expr_code_doover:
}else{
r1 = sqlcipher_sqlite3ExprCodeTemp(pParse, pLeft, &regFree1);
r2 = sqlcipher_sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
- codeCompare(pParse, pLeft, pExpr->pRight, op,
- r1, r2, inReg, SQLITE_STOREP2 | p5,
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_Integer, 1, inReg);
+ codeCompare(pParse, pLeft, pExpr->pRight, op, r1, r2,
+ sqlcipher_sqlite3VdbeCurrentAddr(v)+2, p5,
ExprHasProperty(pExpr,EP_Commuted));
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);
@@ -108904,6 +113133,11 @@ expr_code_doover:
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);
+ if( p5==SQLITE_NULLEQ ){
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_Integer, 0, inReg);
+ }else{
+ sqlcipher_sqlite3VdbeAddOp3(v, OP_ZeroOrNull, r1, inReg, r2);
+ }
testcase( regFree1==0 );
testcase( regFree2==0 );
}
@@ -109006,7 +113240,7 @@ expr_code_doover:
|| NEVER(pExpr->iAgg>=pInfo->nFunc)
){
assert( !ExprHasProperty(pExpr, EP_IntValue) );
- sqlcipher_sqlite3ErrorMsg(pParse, "misuse of aggregate: %s()", pExpr->u.zToken);
+ sqlcipher_sqlite3ErrorMsg(pParse, "misuse of aggregate: %#T()", pExpr);
}else{
return pInfo->aFunc[pExpr->iAgg].iMem;
}
@@ -109034,8 +113268,8 @@ expr_code_doover:
** multiple times if we know they always give the same result */
return sqlcipher_sqlite3ExprCodeRunJustOnce(pParse, pExpr, -1);
}
- assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
assert( !ExprHasProperty(pExpr, EP_TokenOnly) );
+ assert( ExprUseXList(pExpr) );
pFarg = pExpr->x.pList;
nFarg = pFarg ? pFarg->nExpr : 0;
assert( !ExprHasProperty(pExpr, EP_IntValue) );
@@ -109047,7 +113281,7 @@ expr_code_doover:
}
#endif
if( pDef==0 || pDef->xFinalize!=0 ){
- sqlcipher_sqlite3ErrorMsg(pParse, "unknown function: %s()", zId);
+ sqlcipher_sqlite3ErrorMsg(pParse, "unknown function: %#T()", pExpr);
break;
}
if( pDef->funcFlags & SQLITE_FUNC_INLINE ){
@@ -109123,20 +113357,8 @@ expr_code_doover:
if( !pColl ) pColl = db->pDfltColl;
sqlcipher_sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ);
}
-#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
- if( pDef->funcFlags & SQLITE_FUNC_OFFSET ){
- Expr *pArg = pFarg->a[0].pExpr;
- if( pArg->op==TK_COLUMN ){
- sqlcipher_sqlite3VdbeAddOp3(v, OP_Offset, pArg->iTable, pArg->iColumn, target);
- }else{
- sqlcipher_sqlite3VdbeAddOp2(v, OP_Null, 0, target);
- }
- }else
-#endif
- {
- sqlcipher_sqlite3VdbeAddFunctionCall(pParse, constMask, r1, target, nFarg,
- pDef, pExpr->op2);
- }
+ sqlcipher_sqlite3VdbeAddFunctionCall(pParse, constMask, r1, target, nFarg,
+ pDef, pExpr->op2);
if( nFarg ){
if( constMask==0 ){
sqlcipher_sqlite3ReleaseTempRange(pParse, r1, nFarg);
@@ -109154,7 +113376,10 @@ expr_code_doover:
testcase( op==TK_SELECT );
if( pParse->db->mallocFailed ){
return 0;
- }else if( op==TK_SELECT && (nCol = pExpr->x.pSelect->pEList->nExpr)!=1 ){
+ }else if( op==TK_SELECT
+ && ALWAYS( ExprUseXSelect(pExpr) )
+ && (nCol = pExpr->x.pSelect->pEList->nExpr)!=1
+ ){
sqlcipher_sqlite3SubselectError(pParse, nCol, 1);
}else{
return sqlcipher_sqlite3CodeSubselect(pParse, pExpr);
@@ -109163,17 +113388,18 @@ expr_code_doover:
}
case TK_SELECT_COLUMN: {
int n;
- if( pExpr->pLeft->iTable==0 ){
- pExpr->pLeft->iTable = sqlcipher_sqlite3CodeSubselect(pParse, pExpr->pLeft);
+ Expr *pLeft = pExpr->pLeft;
+ if( pLeft->iTable==0 || pParse->withinRJSubrtn > pLeft->op2 ){
+ pLeft->iTable = sqlcipher_sqlite3CodeSubselect(pParse, pLeft);
+ pLeft->op2 = pParse->withinRJSubrtn;
}
- assert( pExpr->iTable==0 || pExpr->pLeft->op==TK_SELECT );
- if( pExpr->iTable!=0
- && pExpr->iTable!=(n = sqlcipher_sqlite3ExprVectorSize(pExpr->pLeft))
- ){
+ assert( pLeft->op==TK_SELECT || pLeft->op==TK_ERROR );
+ n = sqlcipher_sqlite3ExprVectorSize(pLeft);
+ if( pExpr->iTable!=n ){
sqlcipher_sqlite3ErrorMsg(pParse, "%d columns assigned %d values",
pExpr->iTable, n);
}
- return pExpr->pLeft->iTable + pExpr->iColumn;
+ return pLeft->iTable + pExpr->iColumn;
}
case TK_IN: {
int destIfFalse = sqlcipher_sqlite3VdbeMakeLabel(pParse);
@@ -109204,8 +113430,24 @@ expr_code_doover:
exprCodeBetween(pParse, pExpr, target, 0, 0);
return target;
}
+ case TK_COLLATE: {
+ if( !ExprHasProperty(pExpr, EP_Collate)
+ && ALWAYS(pExpr->pLeft)
+ && pExpr->pLeft->op==TK_FUNCTION
+ ){
+ inReg = sqlcipher_sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
+ if( inReg!=target ){
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_SCopy, inReg, target);
+ inReg = target;
+ }
+ sqlcipher_sqlite3VdbeAddOp1(v, OP_ClrSubtype, inReg);
+ return inReg;
+ }else{
+ pExpr = pExpr->pLeft;
+ goto expr_code_doover; /* 2018-04-28: Prevent deep recursion. */
+ }
+ }
case TK_SPAN:
- case TK_COLLATE:
case TK_UPLUS: {
pExpr = pExpr->pLeft;
goto expr_code_doover; /* 2018-04-28: Prevent deep recursion. OSSFuzz. */
@@ -109237,9 +113479,14 @@ expr_code_doover:
** p1==1 -> old.a p1==4 -> new.a
** p1==2 -> old.b p1==5 -> new.b
*/
- Table *pTab = pExpr->y.pTab;
- int iCol = pExpr->iColumn;
- int p1 = pExpr->iTable * (pTab->nCol+1) + 1
+ Table *pTab;
+ int iCol;
+ int p1;
+
+ assert( ExprUseYTab(pExpr) );
+ pTab = pExpr->y.pTab;
+ iCol = pExpr->iColumn;
+ p1 = pExpr->iTable * (pTab->nCol+1) + 1
+ sqlcipher_sqlite3TableColumnToStorage(pTab, iCol);
assert( pExpr->iTable==0 || pExpr->iTable==1 );
@@ -109250,7 +113497,7 @@ expr_code_doover:
sqlcipher_sqlite3VdbeAddOp2(v, OP_Param, p1, target);
VdbeComment((v, "r[%d]=%s.%s", target,
(pExpr->iTable ? "new" : "old"),
- (pExpr->iColumn<0 ? "rowid" : pExpr->y.pTab->aCol[iCol].zName)
+ (pExpr->iColumn<0 ? "rowid" : pExpr->y.pTab->aCol[iCol].zCnName)
));
#ifndef SQLITE_OMIT_FLOATING_POINT
@@ -109327,7 +113574,7 @@ expr_code_doover:
Expr *pDel = 0;
sqlcipher_sqlite3 *db = pParse->db;
- assert( !ExprHasProperty(pExpr, EP_xIsSelect) && pExpr->x.pList );
+ assert( ExprUseXList(pExpr) && pExpr->x.pList!=0 );
assert(pExpr->x.pList->nExpr > 0);
pEList = pExpr->x.pList;
aListelem = pEList->a;
@@ -109441,7 +113688,9 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ExprCodeRunJustOnce(
struct ExprList_item *pItem;
int i;
for(pItem=p->a, i=p->nExpr; i>0; pItem++, i--){
- if( pItem->reusable && sqlcipher_sqlite3ExprCompare(0,pItem->pExpr,pExpr,-1)==0 ){
+ if( pItem->fg.reusable
+ && sqlcipher_sqlite3ExprCompare(0,pItem->pExpr,pExpr,-1)==0
+ ){
return pItem->u.iConstExprReg;
}
}
@@ -109464,7 +113713,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ExprCodeRunJustOnce(
p = sqlcipher_sqlite3ExprListAppend(pParse, p, pExpr);
if( p ){
struct ExprList_item *pItem = &p->a[p->nExpr-1];
- pItem->reusable = regDest<0;
+ pItem->fg.reusable = regDest<0;
if( regDest<0 ) regDest = ++pParse->nMem;
pItem->u.iConstExprReg = regDest;
}
@@ -109524,7 +113773,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3ExprCode(Parse *pParse, Expr *pExpr, int ta
inReg = sqlcipher_sqlite3ExprCodeTarget(pParse, pExpr, target);
if( inReg!=target ){
u8 op;
- if( ExprHasProperty(pExpr,EP_Subquery) ){
+ if( ALWAYS(pExpr) && ExprHasProperty(pExpr,EP_Subquery) ){
op = OP_Copy;
}else{
op = OP_SCopy;
@@ -109598,7 +113847,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ExprCodeExprList(
for(pItem=pList->a, i=0; i<n; i++, pItem++){
Expr *pExpr = pItem->pExpr;
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
- if( pItem->bSorterRef ){
+ if( pItem->fg.bSorterRef ){
i--;
n--;
}else
@@ -109672,7 +113921,7 @@ static void exprCodeBetween(
memset(&compRight, 0, sizeof(Expr));
memset(&exprAnd, 0, sizeof(Expr));
- assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
+ assert( ExprUseXList(pExpr) );
pDel = sqlcipher_sqlite3ExprDup(db, pExpr->pLeft, 0);
if( db->mallocFailed==0 ){
exprAnd.op = TK_AND;
@@ -109692,8 +113941,8 @@ static void exprCodeBetween(
** so that the sqlcipher_sqlite3ExprCodeTarget() routine will not attempt to move
** it into the Parse.pConstExpr list. We should use a new bit for this,
** for clarity, but we are out of bits in the Expr.flags field so we
- ** have to reuse the EP_FromJoin bit. Bummer. */
- pDel->flags |= EP_FromJoin;
+ ** have to reuse the EP_OuterON bit. Bummer. */
+ pDel->flags |= EP_OuterON;
sqlcipher_sqlite3ExprCodeTarget(pParse, &exprAnd, dest);
}
sqlcipher_sqlite3ReleaseTempReg(pParse, regFree1);
@@ -110062,7 +114311,11 @@ SQLITE_PRIVATE void sqlcipher_sqlite3ExprIfFalseDup(Parse *pParse, Expr *pExpr,
** Otherwise, if the values are not the same or if pExpr is not a simple
** SQL value, zero is returned.
*/
-static int exprCompareVariable(Parse *pParse, Expr *pVar, Expr *pExpr){
+static int exprCompareVariable(
+ const Parse *pParse,
+ const Expr *pVar,
+ const Expr *pExpr
+){
int res = 0;
int iVar;
sqlcipher_sqlite3_value *pL, *pR = 0;
@@ -110114,7 +114367,12 @@ static int exprCompareVariable(Parse *pParse, Expr *pVar, Expr *pExpr){
** Argument pParse should normally be NULL. If it is not NULL and pA or
** pB causes a return value of 2.
*/
-SQLITE_PRIVATE int sqlcipher_sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTab){
+SQLITE_PRIVATE int sqlcipher_sqlite3ExprCompare(
+ const Parse *pParse,
+ const Expr *pA,
+ const Expr *pB,
+ int iTab
+){
u32 combinedFlags;
if( pA==0 || pB==0 ){
return pB==pA ? 0 : 2;
@@ -110138,7 +114396,9 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *p
}
return 2;
}
- if( pA->op!=TK_COLUMN && pA->op!=TK_AGG_COLUMN && pA->u.zToken ){
+ assert( !ExprHasProperty(pA, EP_IntValue) );
+ assert( !ExprHasProperty(pB, EP_IntValue) );
+ if( pA->u.zToken ){
if( pA->op==TK_FUNCTION || pA->op==TK_AGG_FUNCTION ){
if( sqlcipher_sqlite3StrICmp(pA->u.zToken,pB->u.zToken)!=0 ) return 2;
#ifndef SQLITE_OMIT_WINDOWFUNC
@@ -110156,7 +114416,12 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *p
return 0;
}else if( pA->op==TK_COLLATE ){
if( sqlcipher_sqlite3_stricmp(pA->u.zToken,pB->u.zToken)!=0 ) return 2;
- }else if( ALWAYS(pB->u.zToken!=0) && strcmp(pA->u.zToken,pB->u.zToken)!=0 ){
+ }else
+ if( pB->u.zToken!=0
+ && pA->op!=TK_COLUMN
+ && pA->op!=TK_AGG_COLUMN
+ && strcmp(pA->u.zToken,pB->u.zToken)!=0
+ ){
return 2;
}
}
@@ -110198,7 +114463,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *p
** Two NULL pointers are considered to be the same. But a NULL pointer
** always differs from a non-NULL pointer.
*/
-SQLITE_PRIVATE int sqlcipher_sqlite3ExprListCompare(ExprList *pA, ExprList *pB, int iTab){
+SQLITE_PRIVATE int sqlcipher_sqlite3ExprListCompare(const ExprList *pA, const ExprList *pB, int iTab){
int i;
if( pA==0 && pB==0 ) return 0;
if( pA==0 || pB==0 ) return 1;
@@ -110207,7 +114472,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ExprListCompare(ExprList *pA, ExprList *pB,
int res;
Expr *pExprA = pA->a[i].pExpr;
Expr *pExprB = pB->a[i].pExpr;
- if( pA->a[i].sortFlags!=pB->a[i].sortFlags ) return 1;
+ if( pA->a[i].fg.sortFlags!=pB->a[i].fg.sortFlags ) return 1;
if( (res = sqlcipher_sqlite3ExprCompare(0, pExprA, pExprB, iTab)) ) return res;
}
return 0;
@@ -110217,7 +114482,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ExprListCompare(ExprList *pA, ExprList *pB,
** Like sqlcipher_sqlite3ExprCompare() except COLLATE operators at the top-level
** are ignored.
*/
-SQLITE_PRIVATE int sqlcipher_sqlite3ExprCompareSkip(Expr *pA, Expr *pB, int iTab){
+SQLITE_PRIVATE int sqlcipher_sqlite3ExprCompareSkip(Expr *pA,Expr *pB, int iTab){
return sqlcipher_sqlite3ExprCompare(0,
sqlcipher_sqlite3ExprSkipCollateAndLikely(pA),
sqlcipher_sqlite3ExprSkipCollateAndLikely(pB),
@@ -110231,9 +114496,9 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ExprCompareSkip(Expr *pA, Expr *pB, int iTab
** non-NULL if pNN is not NULL
*/
static int exprImpliesNotNull(
- Parse *pParse, /* Parsing context */
- Expr *p, /* The expression to be checked */
- Expr *pNN, /* The expression that is NOT NULL */
+ const Parse *pParse,/* Parsing context */
+ const Expr *p, /* The expression to be checked */
+ const Expr *pNN, /* The expression that is NOT NULL */
int iTab, /* Table being evaluated */
int seenNot /* Return true only if p can be any non-NULL value */
){
@@ -110245,12 +114510,13 @@ static int exprImpliesNotNull(
switch( p->op ){
case TK_IN: {
if( seenNot && ExprHasProperty(p, EP_xIsSelect) ) return 0;
- assert( ExprHasProperty(p,EP_xIsSelect)
- || (p->x.pList!=0 && p->x.pList->nExpr>0) );
+ assert( ExprUseXSelect(p) || (p->x.pList!=0 && p->x.pList->nExpr>0) );
return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, 1);
}
case TK_BETWEEN: {
- ExprList *pList = p->x.pList;
+ ExprList *pList;
+ assert( ExprUseXList(p) );
+ pList = p->x.pList;
assert( pList!=0 );
assert( pList->nExpr==2 );
if( seenNot ) return 0;
@@ -110326,7 +114592,12 @@ static int exprImpliesNotNull(
** improvement. Returning false might cause a performance reduction, but
** it will always give the correct answer and is hence always safe.
*/
-SQLITE_PRIVATE int sqlcipher_sqlite3ExprImpliesExpr(Parse *pParse, Expr *pE1, Expr *pE2, int iTab){
+SQLITE_PRIVATE int sqlcipher_sqlite3ExprImpliesExpr(
+ const Parse *pParse,
+ const Expr *pE1,
+ const Expr *pE2,
+ int iTab
+){
if( sqlcipher_sqlite3ExprCompare(pParse, pE1, pE2, iTab)==0 ){
return 1;
}
@@ -110356,7 +114627,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ExprImpliesExpr(Parse *pParse, Expr *pE1, Ex
static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
testcase( pExpr->op==TK_AGG_COLUMN );
testcase( pExpr->op==TK_AGG_FUNCTION );
- if( ExprHasProperty(pExpr, EP_FromJoin) ) return WRC_Prune;
+ if( ExprHasProperty(pExpr, EP_OuterON) ) return WRC_Prune;
switch( pExpr->op ){
case TK_ISNOT:
case TK_ISNULL:
@@ -110422,10 +114693,14 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
testcase( pExpr->op==TK_GE );
/* The y.pTab=0 assignment in wherecode.c always happens after the
** impliesNotNullRow() test */
- if( (pLeft->op==TK_COLUMN && ALWAYS(pLeft->y.pTab!=0)
- && IsVirtual(pLeft->y.pTab))
- || (pRight->op==TK_COLUMN && ALWAYS(pRight->y.pTab!=0)
- && IsVirtual(pRight->y.pTab))
+ assert( pLeft->op!=TK_COLUMN || ExprUseYTab(pLeft) );
+ assert( pRight->op!=TK_COLUMN || ExprUseYTab(pRight) );
+ if( (pLeft->op==TK_COLUMN
+ && pLeft->y.pTab!=0
+ && IsVirtual(pLeft->y.pTab))
+ || (pRight->op==TK_COLUMN
+ && pRight->y.pTab!=0
+ && IsVirtual(pRight->y.pTab))
){
return WRC_Prune;
}
@@ -110449,8 +114724,8 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
** False positives are not allowed, however. A false positive may result
** in an incorrect answer.
**
-** Terms of p that are marked with EP_FromJoin (and hence that come from
-** the ON or USING clauses of LEFT JOINS) are excluded from the analysis.
+** Terms of p that are marked with EP_OuterON (and hence that come from
+** the ON or USING clauses of OUTER JOINS) are excluded from the analysis.
**
** This routine is used to check if a LEFT JOIN can be converted into
** an ordinary JOIN. The p argument is the WHERE clause. If the WHERE
@@ -110534,88 +114809,125 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ExprCoveredByIndex(
}
-/*
-** An instance of the following structure is used by the tree walker
-** to count references to table columns in the arguments of an
-** aggregate function, in order to implement the
-** sqlcipher_sqlite3FunctionThisSrc() routine.
-*/
-struct SrcCount {
- SrcList *pSrc; /* One particular FROM clause in a nested query */
- int iSrcInner; /* Smallest cursor number in this context */
- int nThis; /* Number of references to columns in pSrcList */
- int nOther; /* Number of references to columns in other FROM clauses */
+/* Structure used to pass information throught the Walker in order to
+** implement sqlcipher_sqlite3ReferencesSrcList().
+*/
+struct RefSrcList {
+ sqlcipher_sqlite3 *db; /* Database connection used for sqlcipher_sqlite3DbRealloc() */
+ SrcList *pRef; /* Looking for references to these tables */
+ i64 nExclude; /* Number of tables to exclude from the search */
+ int *aiExclude; /* Cursor IDs for tables to exclude from the search */
};
/*
-** xSelect callback for sqlcipher_sqlite3FunctionUsesThisSrc(). If this is the first
-** SELECT with a FROM clause encountered during this iteration, set
-** SrcCount.iSrcInner to the cursor number of the leftmost object in
-** the FROM cause.
+** Walker SELECT callbacks for sqlcipher_sqlite3ReferencesSrcList().
+**
+** When entering a new subquery on the pExpr argument, add all FROM clause
+** entries for that subquery to the exclude list.
+**
+** When leaving the subquery, remove those entries from the exclude list.
*/
-static int selectSrcCount(Walker *pWalker, Select *pSel){
- struct SrcCount *p = pWalker->u.pSrcCount;
- if( p->iSrcInner==0x7FFFFFFF && ALWAYS(pSel->pSrc) && pSel->pSrc->nSrc ){
- pWalker->u.pSrcCount->iSrcInner = pSel->pSrc->a[0].iCursor;
+static int selectRefEnter(Walker *pWalker, Select *pSelect){
+ struct RefSrcList *p = pWalker->u.pRefSrcList;
+ SrcList *pSrc = pSelect->pSrc;
+ i64 i, j;
+ int *piNew;
+ if( pSrc->nSrc==0 ) return WRC_Continue;
+ j = p->nExclude;
+ p->nExclude += pSrc->nSrc;
+ piNew = sqlcipher_sqlite3DbRealloc(p->db, p->aiExclude, p->nExclude*sizeof(int));
+ if( piNew==0 ){
+ p->nExclude = 0;
+ return WRC_Abort;
+ }else{
+ p->aiExclude = piNew;
+ }
+ for(i=0; i<pSrc->nSrc; i++, j++){
+ p->aiExclude[j] = pSrc->a[i].iCursor;
}
return WRC_Continue;
}
+static void selectRefLeave(Walker *pWalker, Select *pSelect){
+ struct RefSrcList *p = pWalker->u.pRefSrcList;
+ SrcList *pSrc = pSelect->pSrc;
+ if( p->nExclude ){
+ assert( p->nExclude>=pSrc->nSrc );
+ p->nExclude -= pSrc->nSrc;
+ }
+}
-/*
-** Count the number of references to columns.
+/* This is the Walker EXPR callback for sqlcipher_sqlite3ReferencesSrcList().
+**
+** Set the 0x01 bit of pWalker->eCode if there is a reference to any
+** of the tables shown in RefSrcList.pRef.
+**
+** Set the 0x02 bit of pWalker->eCode if there is a reference to a
+** table is in neither RefSrcList.pRef nor RefSrcList.aiExclude.
*/
-static int exprSrcCount(Walker *pWalker, Expr *pExpr){
- /* There was once a NEVER() on the second term on the grounds that
- ** sqlcipher_sqlite3FunctionUsesThisSrc() was always called before
- ** sqlcipher_sqlite3ExprAnalyzeAggregates() and so the TK_COLUMNs have not yet
- ** been converted into TK_AGG_COLUMN. But this is no longer true due
- ** to window functions - sqlcipher_sqlite3WindowRewrite() may now indirectly call
- ** FunctionUsesThisSrc() when creating a new sub-select. */
- if( pExpr->op==TK_COLUMN || pExpr->op==TK_AGG_COLUMN ){
+static int exprRefToSrcList(Walker *pWalker, Expr *pExpr){
+ if( pExpr->op==TK_COLUMN
+ || pExpr->op==TK_AGG_COLUMN
+ ){
int i;
- struct SrcCount *p = pWalker->u.pSrcCount;
- SrcList *pSrc = p->pSrc;
+ struct RefSrcList *p = pWalker->u.pRefSrcList;
+ SrcList *pSrc = p->pRef;
int nSrc = pSrc ? pSrc->nSrc : 0;
for(i=0; i<nSrc; i++){
- if( pExpr->iTable==pSrc->a[i].iCursor ) break;
+ if( pExpr->iTable==pSrc->a[i].iCursor ){
+ pWalker->eCode |= 1;
+ return WRC_Continue;
+ }
}
- if( i<nSrc ){
- p->nThis++;
- }else if( pExpr->iTable<p->iSrcInner ){
- /* In a well-formed parse tree (no name resolution errors),
- ** TK_COLUMN nodes with smaller Expr.iTable values are in an
- ** outer context. Those are the only ones to count as "other" */
- p->nOther++;
+ for(i=0; i<p->nExclude && p->aiExclude[i]!=pExpr->iTable; i++){}
+ if( i>=p->nExclude ){
+ pWalker->eCode |= 2;
}
}
return WRC_Continue;
}
/*
-** Determine if any of the arguments to the pExpr Function reference
-** pSrcList. Return true if they do. Also return true if the function
-** has no arguments or has only constant arguments. Return false if pExpr
-** references columns but not columns of tables found in pSrcList.
+** Check to see if pExpr references any tables in pSrcList.
+** Possible return values:
+**
+** 1 pExpr does references a table in pSrcList.
+**
+** 0 pExpr references some table that is not defined in either
+** pSrcList or in subqueries of pExpr itself.
+**
+** -1 pExpr only references no tables at all, or it only
+** references tables defined in subqueries of pExpr itself.
+**
+** As currently used, pExpr is always an aggregate function call. That
+** fact is exploited for efficiency.
*/
-SQLITE_PRIVATE int sqlcipher_sqlite3FunctionUsesThisSrc(Expr *pExpr, SrcList *pSrcList){
+SQLITE_PRIVATE int sqlcipher_sqlite3ReferencesSrcList(Parse *pParse, Expr *pExpr, SrcList *pSrcList){
Walker w;
- struct SrcCount cnt;
- assert( pExpr->op==TK_AGG_FUNCTION );
+ struct RefSrcList x;
memset(&w, 0, sizeof(w));
- w.xExprCallback = exprSrcCount;
- w.xSelectCallback = selectSrcCount;
- w.u.pSrcCount = &cnt;
- cnt.pSrc = pSrcList;
- cnt.iSrcInner = (pSrcList&&pSrcList->nSrc)?pSrcList->a[0].iCursor:0x7FFFFFFF;
- cnt.nThis = 0;
- cnt.nOther = 0;
+ memset(&x, 0, sizeof(x));
+ w.xExprCallback = exprRefToSrcList;
+ w.xSelectCallback = selectRefEnter;
+ w.xSelectCallback2 = selectRefLeave;
+ w.u.pRefSrcList = &x;
+ x.db = pParse->db;
+ x.pRef = pSrcList;
+ assert( pExpr->op==TK_AGG_FUNCTION );
+ assert( ExprUseXList(pExpr) );
sqlcipher_sqlite3WalkExprList(&w, pExpr->x.pList);
#ifndef SQLITE_OMIT_WINDOWFUNC
if( ExprHasProperty(pExpr, EP_WinFunc) ){
sqlcipher_sqlite3WalkExpr(&w, pExpr->y.pWin->pFilter);
}
#endif
- return cnt.nThis>0 || cnt.nOther==0;
+ sqlcipher_sqlite3DbFree(pParse->db, x.aiExclude);
+ if( w.eCode & 0x01 ){
+ return 1;
+ }else if( w.eCode ){
+ return 0;
+ }else{
+ return -1;
+ }
}
/*
@@ -110646,8 +114958,7 @@ static int agginfoPersistExprCb(Walker *pWalker, Expr *pExpr){
pExpr = sqlcipher_sqlite3ExprDup(db, pExpr, 0);
if( pExpr ){
pAggInfo->aCol[iAgg].pCExpr = pExpr;
- pParse->pConstExpr =
- sqlcipher_sqlite3ExprListAppend(pParse, pParse->pConstExpr, pExpr);
+ sqlcipher_sqlite3ExprDeferredDelete(pParse, pExpr);
}
}
}else{
@@ -110656,8 +114967,7 @@ static int agginfoPersistExprCb(Walker *pWalker, Expr *pExpr){
pExpr = sqlcipher_sqlite3ExprDup(db, pExpr, 0);
if( pExpr ){
pAggInfo->aFunc[iAgg].pFExpr = pExpr;
- pParse->pConstExpr =
- sqlcipher_sqlite3ExprListAppend(pParse, pParse->pConstExpr, pExpr);
+ sqlcipher_sqlite3ExprDeferredDelete(pParse, pExpr);
}
}
}
@@ -110729,7 +115039,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
/* Check to see if the column is in one of the tables in the FROM
** clause of the aggregate query */
if( ALWAYS(pSrcList!=0) ){
- struct SrcList_item *pItem = pSrcList->a;
+ SrcItem *pItem = pSrcList->a;
for(i=0; i<pSrcList->nSrc; i++, pItem++){
struct AggInfo_col *pCol;
assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) );
@@ -110752,6 +115062,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
&& (k = addAggInfoColumn(pParse->db, pAggInfo))>=0
){
pCol = &pAggInfo->aCol[k];
+ assert( ExprUseYTab(pExpr) );
pCol->pTab = pExpr->y.pTab;
pCol->iTable = pExpr->iTable;
pCol->iColumn = pExpr->iColumn;
@@ -110800,6 +115111,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
*/
struct AggInfo_func *pItem = pAggInfo->aFunc;
for(i=0; i<pAggInfo->nFunc; i++, pItem++){
+ if( pItem->pFExpr==pExpr ) break;
if( sqlcipher_sqlite3ExprCompare(0, pItem->pFExpr, pExpr, -1)==0 ){
break;
}
@@ -110814,7 +115126,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
pItem = &pAggInfo->aFunc[i];
pItem->pFExpr = pExpr;
pItem->iMem = ++pParse->nMem;
- assert( !ExprHasProperty(pExpr, EP_IntValue) );
+ assert( ExprUseUToken(pExpr) );
pItem->pFunc = sqlcipher_sqlite3FindFunction(pParse->db,
pExpr->u.zToken,
pExpr->x.pList ? pExpr->x.pList->nExpr : 0, enc, 0);
@@ -111000,6 +115312,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3NoTempsInRange(Parse *pParse, int iFirst, in
static int isAlterableTable(Parse *pParse, Table *pTab){
if( 0==sqlcipher_sqlite3StrNICmp(pTab->zName, "sqlite_", 7)
#ifndef SQLITE_OMIT_VIRTUALTABLE
+ || (pTab->tabFlags & TF_Eponymous)!=0
|| ( (pTab->tabFlags & TF_Shadow)!=0
&& sqlcipher_sqlite3ReadOnlyShadowTables(pParse->db)
)
@@ -111018,25 +115331,56 @@ static int isAlterableTable(Parse *pParse, Table *pTab){
** statement to ensure that the operation has not rendered any schema
** objects unusable.
*/
-static void renameTestSchema(Parse *pParse, const char *zDb, int bTemp){
+static void renameTestSchema(
+ Parse *pParse, /* Parse context */
+ const char *zDb, /* Name of db to verify schema of */
+ int bTemp, /* True if this is the temp db */
+ const char *zWhen, /* "when" part of error message */
+ int bNoDQS /* Do not allow DQS in the schema */
+){
+ pParse->colNamesSet = 1;
sqlcipher_sqlite3NestedParse(pParse,
"SELECT 1 "
- "FROM \"%w\"." DFLT_SCHEMA_TABLE " "
+ "FROM \"%w\"." LEGACY_SCHEMA_TABLE " "
"WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"
" AND sql NOT LIKE 'create virtual%%'"
- " AND sqlite_rename_test(%Q, sql, type, name, %d)=NULL ",
+ " AND sqlite_rename_test(%Q, sql, type, name, %d, %Q, %d)=NULL ",
zDb,
- zDb, bTemp
+ zDb, bTemp, zWhen, bNoDQS
);
if( bTemp==0 ){
sqlcipher_sqlite3NestedParse(pParse,
"SELECT 1 "
- "FROM temp." DFLT_SCHEMA_TABLE " "
+ "FROM temp." LEGACY_SCHEMA_TABLE " "
"WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"
" AND sql NOT LIKE 'create virtual%%'"
- " AND sqlite_rename_test(%Q, sql, type, name, 1)=NULL ",
- zDb
+ " AND sqlite_rename_test(%Q, sql, type, name, 1, %Q, %d)=NULL ",
+ zDb, zWhen, bNoDQS
+ );
+ }
+}
+
+/*
+** Generate VM code to replace any double-quoted strings (but not double-quoted
+** identifiers) within the "sql" column of the sqlite_schema table in
+** database zDb with their single-quoted equivalents. If argument bTemp is
+** not true, similarly update all SQL statements in the sqlite_schema table
+** of the temp db.
+*/
+static void renameFixQuotes(Parse *pParse, const char *zDb, int bTemp){
+ sqlcipher_sqlite3NestedParse(pParse,
+ "UPDATE \"%w\"." LEGACY_SCHEMA_TABLE
+ " SET sql = sqlite_rename_quotefix(%Q, sql)"
+ "WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"
+ " AND sql NOT LIKE 'create virtual%%'" , zDb, zDb
+ );
+ if( bTemp==0 ){
+ sqlcipher_sqlite3NestedParse(pParse,
+ "UPDATE temp." LEGACY_SCHEMA_TABLE
+ " SET sql = sqlite_rename_quotefix('temp', sql)"
+ "WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"
+ " AND sql NOT LIKE 'create virtual%%'"
);
}
}
@@ -111045,12 +115389,12 @@ static void renameTestSchema(Parse *pParse, const char *zDb, int bTemp){
** Generate code to reload the schema for database iDb. And, if iDb!=1, for
** the temp database as well.
*/
-static void renameReloadSchema(Parse *pParse, int iDb){
+static void renameReloadSchema(Parse *pParse, int iDb, u16 p5){
Vdbe *v = pParse->pVdbe;
if( v ){
sqlcipher_sqlite3ChangeCookie(pParse, iDb);
- sqlcipher_sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, iDb, 0);
- if( iDb!=1 ) sqlcipher_sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, 1, 0);
+ sqlcipher_sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, iDb, 0, p5);
+ if( iDb!=1 ) sqlcipher_sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, 1, 0, p5);
}
}
@@ -111072,9 +115416,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3AlterRenameTable(
const char *zTabName; /* Original name of the table */
Vdbe *v;
VTable *pVTab = 0; /* Non-zero if this is a v-tab with an xRename() */
- u32 savedDbFlags; /* Saved value of db->mDbFlags */
- savedDbFlags = db->mDbFlags;
if( NEVER(db->mallocFailed) ) goto exit_rename_table;
assert( pSrc->nSrc==1 );
assert( sqlcipher_sqlite3BtreeHoldsAllMutexes(pParse->db) );
@@ -111083,7 +115425,6 @@ SQLITE_PRIVATE void sqlcipher_sqlite3AlterRenameTable(
if( !pTab ) goto exit_rename_table;
iDb = sqlcipher_sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
zDb = db->aDb[iDb].zDbSName;
- db->mDbFlags |= DBFLAG_PreferBuiltin;
/* Get a NULL terminated version of the new table name. */
zName = sqlcipher_sqlite3NameFromToken(db, pName);
@@ -111112,7 +115453,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3AlterRenameTable(
}
#ifndef SQLITE_OMIT_VIEW
- if( pTab->pSelect ){
+ if( IsView(pTab) ){
sqlcipher_sqlite3ErrorMsg(pParse, "view %s may not be altered", pTab->zName);
goto exit_rename_table;
}
@@ -111154,7 +115495,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3AlterRenameTable(
/* Rewrite all CREATE TABLE, INDEX, TRIGGER or VIEW statements in
** the schema to use the new table name. */
sqlcipher_sqlite3NestedParse(pParse,
- "UPDATE \"%w\"." DFLT_SCHEMA_TABLE " SET "
+ "UPDATE \"%w\"." LEGACY_SCHEMA_TABLE " SET "
"sql = sqlite_rename_table(%Q, type, name, sql, %Q, %Q, %d) "
"WHERE (type!='index' OR tbl_name=%Q COLLATE nocase)"
"AND name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"
@@ -111164,7 +115505,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3AlterRenameTable(
/* Update the tbl_name and name columns of the sqlite_schema table
** as required. */
sqlcipher_sqlite3NestedParse(pParse,
- "UPDATE %Q." DFLT_SCHEMA_TABLE " SET "
+ "UPDATE %Q." LEGACY_SCHEMA_TABLE " SET "
"tbl_name = %Q, "
"name = CASE "
"WHEN type='table' THEN %Q "
@@ -111199,7 +115540,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3AlterRenameTable(
"sql = sqlite_rename_table(%Q, type, name, sql, %Q, %Q, 1), "
"tbl_name = "
"CASE WHEN tbl_name=%Q COLLATE nocase AND "
- " sqlite_rename_test(%Q, sql, type, name, 1) "
+ " sqlite_rename_test(%Q, sql, type, name, 1, 'after rename', 0) "
"THEN %Q ELSE tbl_name END "
"WHERE type IN ('view', 'trigger')"
, zDb, zTabName, zName, zTabName, zDb, zName);
@@ -111218,13 +115559,12 @@ SQLITE_PRIVATE void sqlcipher_sqlite3AlterRenameTable(
}
#endif
- renameReloadSchema(pParse, iDb);
- renameTestSchema(pParse, zDb, iDb==1);
+ renameReloadSchema(pParse, iDb, INITFLAG_AlterRename);
+ renameTestSchema(pParse, zDb, iDb==1, "after rename", 0);
exit_rename_table:
sqlcipher_sqlite3SrcListDelete(db, pSrc);
sqlcipher_sqlite3DbFree(db, zName);
- db->mDbFlags = savedDbFlags;
}
/*
@@ -111265,7 +115605,9 @@ SQLITE_PRIVATE void sqlcipher_sqlite3AlterFinishAddColumn(Parse *pParse, Token *
int r1; /* Temporary registers */
db = pParse->db;
- if( pParse->nErr || db->mallocFailed ) return;
+ assert( db->pParse==pParse );
+ if( pParse->nErr ) return;
+ assert( db->mallocFailed==0 );
pNew = pParse->pNewTable;
assert( pNew );
@@ -111274,7 +115616,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3AlterFinishAddColumn(Parse *pParse, Token *
zDb = db->aDb[iDb].zDbSName;
zTab = &pNew->zName[16]; /* Skip the "sqlite_altertab_" prefix on the name */
pCol = &pNew->aCol[pNew->nCol-1];
- pDflt = pCol->pDflt;
+ pDflt = sqlcipher_sqlite3ColumnExpr(pNew, pCol);
pTab = sqlcipher_sqlite3FindTable(db, zTab, zDb);
assert( pTab );
@@ -111308,7 +115650,8 @@ SQLITE_PRIVATE void sqlcipher_sqlite3AlterFinishAddColumn(Parse *pParse, Token *
if( pDflt && pDflt->pLeft->op==TK_NULL ){
pDflt = 0;
}
- if( (db->flags&SQLITE_ForeignKeys) && pNew->pFKey && pDflt ){
+ assert( IsOrdinaryTable(pNew) );
+ if( (db->flags&SQLITE_ForeignKeys) && pNew->u.tab.pFKey && pDflt ){
sqlcipher_sqlite3ErrorIfNotEmpty(pParse, zDb, zTab,
"Cannot add a REFERENCES column with non-NULL default value");
}
@@ -111345,28 +115688,30 @@ SQLITE_PRIVATE void sqlcipher_sqlite3AlterFinishAddColumn(Parse *pParse, Token *
zCol = sqlcipher_sqlite3DbStrNDup(db, (char*)pColDef->z, pColDef->n);
if( zCol ){
char *zEnd = &zCol[pColDef->n-1];
- u32 savedDbFlags = db->mDbFlags;
while( zEnd>zCol && (*zEnd==';' || sqlcipher_sqlite3Isspace(*zEnd)) ){
*zEnd-- = '\0';
}
- db->mDbFlags |= DBFLAG_PreferBuiltin;
+ /* substr() operations on characters, but addColOffset is in bytes. So we
+ ** have to use printf() to translate between these units: */
+ assert( IsOrdinaryTable(pTab) );
+ assert( IsOrdinaryTable(pNew) );
sqlcipher_sqlite3NestedParse(pParse,
- "UPDATE \"%w\"." DFLT_SCHEMA_TABLE " SET "
- "sql = substr(sql,1,%d) || ', ' || %Q || substr(sql,%d) "
+ "UPDATE \"%w\"." LEGACY_SCHEMA_TABLE " SET "
+ "sql = printf('%%.%ds, ',sql) || %Q"
+ " || substr(sql,1+length(printf('%%.%ds',sql))) "
"WHERE type = 'table' AND name = %Q",
- zDb, pNew->addColOffset, zCol, pNew->addColOffset+1,
+ zDb, pNew->u.tab.addColOffset, zCol, pNew->u.tab.addColOffset,
zTab
);
sqlcipher_sqlite3DbFree(db, zCol);
- db->mDbFlags = savedDbFlags;
}
- /* Make sure the schema version is at least 3. But do not upgrade
- ** from less than 3 to 4, as that will corrupt any preexisting DESC
- ** index.
- */
v = sqlcipher_sqlite3GetVdbe(pParse);
if( v ){
+ /* Make sure the schema version is at least 3. But do not upgrade
+ ** from less than 3 to 4, as that will corrupt any preexisting DESC
+ ** index.
+ */
r1 = sqlcipher_sqlite3GetTempReg(pParse);
sqlcipher_sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, r1, BTREE_FILE_FORMAT);
sqlcipher_sqlite3VdbeUsesBtree(v, iDb);
@@ -111375,10 +115720,25 @@ SQLITE_PRIVATE void sqlcipher_sqlite3AlterFinishAddColumn(Parse *pParse, Token *
VdbeCoverage(v);
sqlcipher_sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_FILE_FORMAT, 3);
sqlcipher_sqlite3ReleaseTempReg(pParse, r1);
- }
- /* Reload the table definition */
- renameReloadSchema(pParse, iDb);
+ /* Reload the table definition */
+ renameReloadSchema(pParse, iDb, INITFLAG_AlterAdd);
+
+ /* Verify that constraints are still satisfied */
+ if( pNew->pCheck!=0
+ || (pCol->notNull && (pCol->colFlags & COLFLAG_GENERATED)!=0)
+ ){
+ sqlcipher_sqlite3NestedParse(pParse,
+ "SELECT CASE WHEN quick_check GLOB 'CHECK*'"
+ " THEN raise(ABORT,'CHECK constraint failed')"
+ " ELSE raise(ABORT,'NOT NULL constraint failed')"
+ " END"
+ " FROM pragma_quick_check(%Q,%Q)"
+ " WHERE quick_check GLOB 'CHECK*' OR quick_check GLOB 'NULL*'",
+ zTab, zDb
+ );
+ }
+ }
}
/*
@@ -111419,7 +115779,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3AlterBeginAddColumn(Parse *pParse, SrcList
#endif
/* Make sure this is not an attempt to ALTER a view. */
- if( pTab->pSelect ){
+ if( IsView(pTab) ){
sqlcipher_sqlite3ErrorMsg(pParse, "Cannot add a column to a view");
goto exit_begin_add_column;
}
@@ -111428,7 +115788,8 @@ SQLITE_PRIVATE void sqlcipher_sqlite3AlterBeginAddColumn(Parse *pParse, SrcList
}
sqlcipher_sqlite3MayAbort(pParse);
- assert( pTab->addColOffset>0 );
+ assert( IsOrdinaryTable(pTab) );
+ assert( pTab->u.tab.addColOffset>0 );
iDb = sqlcipher_sqlite3SchemaToIndex(db, pTab->pSchema);
/* Put a copy of the Table struct in Parse.pNewTable for the
@@ -111455,13 +115816,13 @@ SQLITE_PRIVATE void sqlcipher_sqlite3AlterBeginAddColumn(Parse *pParse, SrcList
memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*pNew->nCol);
for(i=0; i<pNew->nCol; i++){
Column *pCol = &pNew->aCol[i];
- pCol->zName = sqlcipher_sqlite3DbStrDup(db, pCol->zName);
- pCol->hName = sqlcipher_sqlite3StrIHash(pCol->zName);
- pCol->zColl = 0;
- pCol->pDflt = 0;
+ pCol->zCnName = sqlcipher_sqlite3DbStrDup(db, pCol->zCnName);
+ pCol->hName = sqlcipher_sqlite3StrIHash(pCol->zCnName);
}
+ assert( IsOrdinaryTable(pNew) );
+ pNew->u.tab.pDfltList = sqlcipher_sqlite3ExprListDup(db, pTab->u.tab.pDfltList, 0);
pNew->pSchema = db->aDb[iDb].pSchema;
- pNew->addColOffset = pTab->addColOffset;
+ pNew->u.tab.addColOffset = pTab->u.tab.addColOffset;
pNew->nTabRef = 1;
exit_begin_add_column:
@@ -111478,10 +115839,10 @@ exit_begin_add_column:
** Or, if pTab is not a view or virtual table, zero is returned.
*/
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
-static int isRealTable(Parse *pParse, Table *pTab){
+static int isRealTable(Parse *pParse, Table *pTab, int bDrop){
const char *zType = 0;
#ifndef SQLITE_OMIT_VIEW
- if( pTab->pSelect ){
+ if( IsView(pTab) ){
zType = "view";
}
#endif
@@ -111491,15 +115852,16 @@ static int isRealTable(Parse *pParse, Table *pTab){
}
#endif
if( zType ){
- sqlcipher_sqlite3ErrorMsg(
- pParse, "cannot rename columns of %s \"%s\"", zType, pTab->zName
+ sqlcipher_sqlite3ErrorMsg(pParse, "cannot %s %s \"%s\"",
+ (bDrop ? "drop column from" : "rename columns of"),
+ zType, pTab->zName
);
return 1;
}
return 0;
}
#else /* !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) */
-# define isRealTable(x,y) (0)
+# define isRealTable(x,y,z) (0)
#endif
/*
@@ -111528,7 +115890,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3AlterRenameColumn(
/* Cannot alter a system table */
if( SQLITE_OK!=isAlterableTable(pParse, pTab) ) goto exit_rename_column;
- if( SQLITE_OK!=isRealTable(pParse, pTab) ) goto exit_rename_column;
+ if( SQLITE_OK!=isRealTable(pParse, pTab, 0) ) goto exit_rename_column;
/* Which schema holds the table to be altered */
iSchema = sqlcipher_sqlite3SchemaToIndex(db, pTab->pSchema);
@@ -111547,13 +115909,17 @@ SQLITE_PRIVATE void sqlcipher_sqlite3AlterRenameColumn(
zOld = sqlcipher_sqlite3NameFromToken(db, pOld);
if( !zOld ) goto exit_rename_column;
for(iCol=0; iCol<pTab->nCol; iCol++){
- if( 0==sqlcipher_sqlite3StrICmp(pTab->aCol[iCol].zName, zOld) ) break;
+ if( 0==sqlcipher_sqlite3StrICmp(pTab->aCol[iCol].zCnName, zOld) ) break;
}
if( iCol==pTab->nCol ){
- sqlcipher_sqlite3ErrorMsg(pParse, "no such column: \"%s\"", zOld);
+ sqlcipher_sqlite3ErrorMsg(pParse, "no such column: \"%T\"", pOld);
goto exit_rename_column;
}
+ /* Ensure the schema contains no double-quoted strings */
+ renameTestSchema(pParse, zDb, iSchema==1, "", 0);
+ renameFixQuotes(pParse, zDb, iSchema==1);
+
/* Do the rename operation using a recursive UPDATE statement that
** uses the sqlite_rename_column() SQL function to compute the new
** CREATE statement text for the sqlite_schema table.
@@ -111564,26 +115930,25 @@ SQLITE_PRIVATE void sqlcipher_sqlite3AlterRenameColumn(
assert( pNew->n>0 );
bQuote = sqlcipher_sqlite3Isquote(pNew->z[0]);
sqlcipher_sqlite3NestedParse(pParse,
- "UPDATE \"%w\"." DFLT_SCHEMA_TABLE " SET "
+ "UPDATE \"%w\"." LEGACY_SCHEMA_TABLE " SET "
"sql = sqlite_rename_column(sql, type, name, %Q, %Q, %d, %Q, %d, %d) "
"WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X' "
- " AND (type != 'index' OR tbl_name = %Q)"
- " AND sql NOT LIKE 'create virtual%%'",
+ " AND (type != 'index' OR tbl_name = %Q)",
zDb,
zDb, pTab->zName, iCol, zNew, bQuote, iSchema==1,
pTab->zName
);
sqlcipher_sqlite3NestedParse(pParse,
- "UPDATE temp." DFLT_SCHEMA_TABLE " SET "
+ "UPDATE temp." LEGACY_SCHEMA_TABLE " SET "
"sql = sqlite_rename_column(sql, type, name, %Q, %Q, %d, %Q, %d, 1) "
"WHERE type IN ('trigger', 'view')",
zDb, pTab->zName, iCol, zNew, bQuote
);
/* Drop and reload the database schema. */
- renameReloadSchema(pParse, iSchema);
- renameTestSchema(pParse, zDb, iSchema==1);
+ renameReloadSchema(pParse, iSchema, INITFLAG_AlterRename);
+ renameTestSchema(pParse, zDb, iSchema==1, "after rename", 1);
exit_rename_column:
sqlcipher_sqlite3SrcListDelete(db, pSrc);
@@ -111610,7 +115975,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3AlterRenameColumn(
** the parse tree.
*/
struct RenameToken {
- void *p; /* Parse tree element created by token t */
+ const void *p; /* Parse tree element created by token t */
Token t; /* The token that created parse tree element p */
RenameToken *pNext; /* Next is a list of all RenameToken objects */
};
@@ -111652,9 +116017,11 @@ struct RenameCtx {
** Technically, as x no longer points into a valid object or to the byte
** following a valid object, it may not be used in comparison operations.
*/
-static void renameTokenCheckAll(Parse *pParse, void *pPtr){
- if( pParse->nErr==0 && pParse->db->mallocFailed==0 ){
- RenameToken *p;
+static void renameTokenCheckAll(Parse *pParse, const void *pPtr){
+ assert( pParse==pParse->db->pParse );
+ assert( pParse->db->mallocFailed==0 || pParse->nErr!=0 );
+ if( pParse->nErr==0 ){
+ const RenameToken *p;
u8 i = 0;
for(p=pParse->pRename; p; p=p->pNext){
if( p->p ){
@@ -111680,7 +116047,11 @@ static void renameTokenCheckAll(Parse *pParse, void *pPtr){
** with tail recursion in tokenExpr() routine, for a small performance
** improvement.
*/
-SQLITE_PRIVATE void *sqlcipher_sqlite3RenameTokenMap(Parse *pParse, void *pPtr, Token *pToken){
+SQLITE_PRIVATE const void *sqlcipher_sqlite3RenameTokenMap(
+ Parse *pParse,
+ const void *pPtr,
+ const Token *pToken
+){
RenameToken *pNew;
assert( pPtr || pParse->db->mallocFailed );
renameTokenCheckAll(pParse, pPtr);
@@ -111702,7 +116073,7 @@ SQLITE_PRIVATE void *sqlcipher_sqlite3RenameTokenMap(Parse *pParse, void *pPtr,
** with parse tree element pFrom. This function remaps the associated token
** to parse tree element pTo.
*/
-SQLITE_PRIVATE void sqlcipher_sqlite3RenameTokenRemap(Parse *pParse, void *pTo, void *pFrom){
+SQLITE_PRIVATE void sqlcipher_sqlite3RenameTokenRemap(Parse *pParse, const void *pTo, const void *pFrom){
RenameToken *p;
renameTokenCheckAll(pParse, pTo);
for(p=pParse->pRename; p; p=p->pNext){
@@ -111718,7 +116089,10 @@ SQLITE_PRIVATE void sqlcipher_sqlite3RenameTokenRemap(Parse *pParse, void *pTo,
*/
static int renameUnmapExprCb(Walker *pWalker, Expr *pExpr){
Parse *pParse = pWalker->pParse;
- sqlcipher_sqlite3RenameTokenRemap(pParse, 0, (void*)pExpr);
+ sqlcipher_sqlite3RenameTokenRemap(pParse, 0, (const void*)pExpr);
+ if( ExprUseYTab(pExpr) ){
+ sqlcipher_sqlite3RenameTokenRemap(pParse, 0, (const void*)&pExpr->y.pTab);
+ }
return WRC_Continue;
}
@@ -111729,15 +116103,31 @@ static int renameUnmapExprCb(Walker *pWalker, Expr *pExpr){
static void renameWalkWith(Walker *pWalker, Select *pSelect){
With *pWith = pSelect->pWith;
if( pWith ){
+ Parse *pParse = pWalker->pParse;
int i;
+ With *pCopy = 0;
+ assert( pWith->nCte>0 );
+ if( (pWith->a[0].pSelect->selFlags & SF_Expanded)==0 ){
+ /* Push a copy of the With object onto the with-stack. We use a copy
+ ** here as the original will be expanded and resolved (flags SF_Expanded
+ ** and SF_Resolved) below. And the parser code that uses the with-stack
+ ** fails if the Select objects on it have already been expanded and
+ ** resolved. */
+ pCopy = sqlcipher_sqlite3WithDup(pParse->db, pWith);
+ pCopy = sqlcipher_sqlite3WithPush(pParse, pCopy, 1);
+ }
for(i=0; i<pWith->nCte; i++){
Select *p = pWith->a[i].pSelect;
NameContext sNC;
memset(&sNC, 0, sizeof(sNC));
- sNC.pParse = pWalker->pParse;
- sqlcipher_sqlite3SelectPrep(sNC.pParse, p, &sNC);
+ sNC.pParse = pParse;
+ if( pCopy ) sqlcipher_sqlite3SelectPrep(sNC.pParse, p, &sNC);
+ if( sNC.pParse->db->mallocFailed ) return;
sqlcipher_sqlite3WalkSelect(pWalker, p);
- sqlcipher_sqlite3RenameExprlistUnmap(pWalker->pParse, pWith->a[i].pCols);
+ sqlcipher_sqlite3RenameExprlistUnmap(pParse, pWith->a[i].pCols);
+ }
+ if( pCopy && pParse->pWith==pCopy ){
+ pParse->pWith = pCopy->pOuter;
}
}
}
@@ -111747,13 +116137,12 @@ static void renameWalkWith(Walker *pWalker, Select *pSelect){
*/
static void unmapColumnIdlistNames(
Parse *pParse,
- IdList *pIdList
+ const IdList *pIdList
){
- if( pIdList ){
- int ii;
- for(ii=0; ii<pIdList->nId; ii++){
- sqlcipher_sqlite3RenameTokenRemap(pParse, 0, (void*)pIdList->a[ii].zName);
- }
+ int ii;
+ assert( pIdList!=0 );
+ for(ii=0; ii<pIdList->nId; ii++){
+ sqlcipher_sqlite3RenameTokenRemap(pParse, 0, (const void*)pIdList->a[ii].zName);
}
}
@@ -111764,11 +116153,15 @@ static int renameUnmapSelectCb(Walker *pWalker, Select *p){
Parse *pParse = pWalker->pParse;
int i;
if( pParse->nErr ) return WRC_Abort;
- if( NEVER(p->selFlags & SF_View) ) return WRC_Prune;
+ testcase( p->selFlags & SF_View );
+ testcase( p->selFlags & SF_CopyCte );
+ if( p->selFlags & (SF_View|SF_CopyCte) ){
+ return WRC_Prune;
+ }
if( ALWAYS(p->pEList) ){
ExprList *pList = p->pEList;
for(i=0; i<pList->nExpr; i++){
- if( pList->a[i].zEName && pList->a[i].eEName==ENAME_NAME ){
+ if( pList->a[i].zEName && pList->a[i].fg.eEName==ENAME_NAME ){
sqlcipher_sqlite3RenameTokenRemap(pParse, 0, (void*)pList->a[i].zEName);
}
}
@@ -111777,8 +116170,11 @@ static int renameUnmapSelectCb(Walker *pWalker, Select *p){
SrcList *pSrc = p->pSrc;
for(i=0; i<pSrc->nSrc; i++){
sqlcipher_sqlite3RenameTokenRemap(pParse, 0, (void*)pSrc->a[i].zName);
- if( sqlcipher_sqlite3WalkExpr(pWalker, pSrc->a[i].pOn) ) return WRC_Abort;
- unmapColumnIdlistNames(pParse, pSrc->a[i].pUsing);
+ if( pSrc->a[i].fg.isUsing==0 ){
+ sqlcipher_sqlite3WalkExpr(pWalker, pSrc->a[i].u3.pOn);
+ }else{
+ unmapColumnIdlistNames(pParse, pSrc->a[i].u3.pUsing);
+ }
}
}
@@ -111814,7 +116210,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3RenameExprlistUnmap(Parse *pParse, ExprList
sWalker.xExprCallback = renameUnmapExprCb;
sqlcipher_sqlite3WalkExprList(&sWalker, pEList);
for(i=0; i<pEList->nExpr; i++){
- if( ALWAYS(pEList->a[i].eEName==ENAME_NAME) ){
+ if( ALWAYS(pEList->a[i].fg.eEName==ENAME_NAME) ){
sqlcipher_sqlite3RenameTokenRemap(pParse, 0, (void*)pEList->a[i].zEName);
}
}
@@ -111835,23 +116231,35 @@ static void renameTokenFree(sqlcipher_sqlite3 *db, RenameToken *pToken){
/*
** Search the Parse object passed as the first argument for a RenameToken
-** object associated with parse tree element pPtr. If found, remove it
-** from the Parse object and add it to the list maintained by the
-** RenameCtx object passed as the second argument.
+** object associated with parse tree element pPtr. If found, return a pointer
+** to it. Otherwise, return NULL.
+**
+** If the second argument passed to this function is not NULL and a matching
+** RenameToken object is found, remove it from the Parse object and add it to
+** the list maintained by the RenameCtx object.
*/
-static void renameTokenFind(Parse *pParse, struct RenameCtx *pCtx, void *pPtr){
+static RenameToken *renameTokenFind(
+ Parse *pParse,
+ struct RenameCtx *pCtx,
+ const void *pPtr
+){
RenameToken **pp;
- assert( pPtr!=0 );
+ if( NEVER(pPtr==0) ){
+ return 0;
+ }
for(pp=&pParse->pRename; (*pp); pp=&(*pp)->pNext){
if( (*pp)->p==pPtr ){
RenameToken *pToken = *pp;
- *pp = pToken->pNext;
- pToken->pNext = pCtx->pList;
- pCtx->pList = pToken;
- pCtx->nList++;
- break;
+ if( pCtx ){
+ *pp = pToken->pNext;
+ pToken->pNext = pCtx->pList;
+ pCtx->pList = pToken;
+ pCtx->nList++;
+ }
+ return pToken;
}
}
+ return 0;
}
/*
@@ -111860,7 +116268,11 @@ static void renameTokenFind(Parse *pParse, struct RenameCtx *pCtx, void *pPtr){
** descend into sub-select statements.
*/
static int renameColumnSelectCb(Walker *pWalker, Select *p){
- if( p->selFlags & SF_View ) return WRC_Prune;
+ if( p->selFlags & (SF_View|SF_CopyCte) ){
+ testcase( p->selFlags & SF_View );
+ testcase( p->selFlags & SF_CopyCte );
+ return WRC_Prune;
+ }
renameWalkWith(pWalker, p);
return WRC_Continue;
}
@@ -111883,6 +116295,7 @@ static int renameColumnExprCb(Walker *pWalker, Expr *pExpr){
renameTokenFind(pWalker->pParse, p, (void*)pExpr);
}else if( pExpr->op==TK_COLUMN
&& pExpr->iColumn==p->iCol
+ && ALWAYS(ExprUseYTab(pExpr))
&& p->pTab==pExpr->y.pTab
){
renameTokenFind(pWalker->pParse, p, (void*)pExpr);
@@ -111922,7 +116335,7 @@ static RenameToken *renameColumnTokenNext(RenameCtx *pCtx){
*/
static void renameColumnParseError(
sqlcipher_sqlite3_context *pCtx,
- int bPost,
+ const char *zWhen,
sqlcipher_sqlite3_value *pType,
sqlcipher_sqlite3_value *pObject,
Parse *pParse
@@ -111931,12 +116344,12 @@ static void renameColumnParseError(
const char *zN = (const char*)sqlcipher_sqlite3_value_text(pObject);
char *zErr;
- zErr = sqlcipher_sqlite3_mprintf("error in %s %s%s: %s",
- zT, zN, (bPost ? " after rename" : ""),
+ zErr = sqlcipher_sqlite3MPrintf(pParse->db, "error in %s %s%s%s: %s",
+ zT, zN, (zWhen[0] ? " " : ""), zWhen,
pParse->zErrMsg
);
sqlcipher_sqlite3_result_error(pCtx, zErr, -1);
- sqlcipher_sqlite3_free(zErr);
+ sqlcipher_sqlite3DbFree(pParse->db, zErr);
}
/*
@@ -111948,18 +116361,18 @@ static void renameColumnParseError(
static void renameColumnElistNames(
Parse *pParse,
RenameCtx *pCtx,
- ExprList *pEList,
+ const ExprList *pEList,
const char *zOld
){
if( pEList ){
int i;
for(i=0; i<pEList->nExpr; i++){
- char *zName = pEList->a[i].zEName;
- if( ALWAYS(pEList->a[i].eEName==ENAME_NAME)
+ const char *zName = pEList->a[i].zEName;
+ if( ALWAYS(pEList->a[i].fg.eEName==ENAME_NAME)
&& ALWAYS(zName!=0)
&& 0==sqlcipher_sqlite3_stricmp(zName, zOld)
){
- renameTokenFind(pParse, pCtx, (void*)zName);
+ renameTokenFind(pParse, pCtx, (const void*)zName);
}
}
}
@@ -111973,15 +116386,15 @@ static void renameColumnElistNames(
static void renameColumnIdlistNames(
Parse *pParse,
RenameCtx *pCtx,
- IdList *pIdList,
+ const IdList *pIdList,
const char *zOld
){
if( pIdList ){
int i;
for(i=0; i<pIdList->nId; i++){
- char *zName = pIdList->a[i].zName;
+ const char *zName = pIdList->a[i].zName;
if( 0==sqlcipher_sqlite3_stricmp(zName, zOld) ){
- renameTokenFind(pParse, pCtx, (void*)zName);
+ renameTokenFind(pParse, pCtx, (const void*)zName);
}
}
}
@@ -112000,24 +116413,22 @@ static int renameParseSql(
int bTemp /* True if SQL is from temp schema */
){
int rc;
- char *zErr = 0;
+ sqlcipher_sqlite3ParseObjectInit(p, db);
+ if( zSql==0 ){
+ return SQLITE_NOMEM;
+ }
+ if( sqlcipher_sqlite3StrNICmp(zSql,"CREATE ",7)!=0 ){
+ return SQLITE_CORRUPT_BKPT;
+ }
db->init.iDb = bTemp ? 1 : sqlcipher_sqlite3FindDbName(db, zDb);
-
- /* Parse the SQL statement passed as the first argument. If no error
- ** occurs and the parse does not result in a new table, index or
- ** trigger object, the database must be corrupt. */
- memset(p, 0, sizeof(Parse));
p->eParseMode = PARSE_MODE_RENAME;
p->db = db;
p->nQueryLoop = 1;
- rc = sqlcipher_sqlite3RunParser(p, zSql, &zErr);
- assert( p->zErrMsg==0 );
- assert( rc!=SQLITE_OK || zErr==0 );
- p->zErrMsg = zErr;
+ rc = sqlcipher_sqlite3RunParser(p, zSql);
if( db->mallocFailed ) rc = SQLITE_NOMEM;
if( rc==SQLITE_OK
- && p->pNewTable==0 && p->pNewIndex==0 && p->pNewTrigger==0
+ && NEVER(p->pNewTable==0 && p->pNewIndex==0 && p->pNewTrigger==0)
){
rc = SQLITE_CORRUPT_BKPT;
}
@@ -112054,51 +116465,76 @@ static int renameEditSql(
const char *zNew, /* New token text */
int bQuote /* True to always quote token */
){
- int nNew = sqlcipher_sqlite3Strlen30(zNew);
- int nSql = sqlcipher_sqlite3Strlen30(zSql);
+ i64 nNew = sqlcipher_sqlite3Strlen30(zNew);
+ i64 nSql = sqlcipher_sqlite3Strlen30(zSql);
sqlcipher_sqlite3 *db = sqlcipher_sqlite3_context_db_handle(pCtx);
int rc = SQLITE_OK;
- char *zQuot;
+ char *zQuot = 0;
char *zOut;
- int nQuot;
-
- /* Set zQuot to point to a buffer containing a quoted copy of the
- ** identifier zNew. If the corresponding identifier in the original
- ** ALTER TABLE statement was quoted (bQuote==1), then set zNew to
- ** point to zQuot so that all substitutions are made using the
- ** quoted version of the new column name. */
- zQuot = sqlcipher_sqlite3MPrintf(db, "\"%w\"", zNew);
- if( zQuot==0 ){
- return SQLITE_NOMEM;
+ i64 nQuot = 0;
+ char *zBuf1 = 0;
+ char *zBuf2 = 0;
+
+ if( zNew ){
+ /* Set zQuot to point to a buffer containing a quoted copy of the
+ ** identifier zNew. If the corresponding identifier in the original
+ ** ALTER TABLE statement was quoted (bQuote==1), then set zNew to
+ ** point to zQuot so that all substitutions are made using the
+ ** quoted version of the new column name. */
+ zQuot = sqlcipher_sqlite3MPrintf(db, "\"%w\" ", zNew);
+ if( zQuot==0 ){
+ return SQLITE_NOMEM;
+ }else{
+ nQuot = sqlcipher_sqlite3Strlen30(zQuot)-1;
+ }
+
+ assert( nQuot>=nNew );
+ zOut = sqlcipher_sqlite3DbMallocZero(db, nSql + pRename->nList*nQuot + 1);
}else{
- nQuot = sqlcipher_sqlite3Strlen30(zQuot);
- }
- if( bQuote ){
- zNew = zQuot;
- nNew = nQuot;
+ zOut = (char*)sqlcipher_sqlite3DbMallocZero(db, (nSql*2+1) * 3);
+ if( zOut ){
+ zBuf1 = &zOut[nSql*2+1];
+ zBuf2 = &zOut[nSql*4+2];
+ }
}
/* At this point pRename->pList contains a list of RenameToken objects
** corresponding to all tokens in the input SQL that must be replaced
- ** with the new column name. All that remains is to construct and
- ** return the edited SQL string. */
- assert( nQuot>=nNew );
- zOut = sqlcipher_sqlite3DbMallocZero(db, nSql + pRename->nList*nQuot + 1);
+ ** with the new column name, or with single-quoted versions of themselves.
+ ** All that remains is to construct and return the edited SQL string. */
if( zOut ){
int nOut = nSql;
memcpy(zOut, zSql, nSql);
while( pRename->pList ){
int iOff; /* Offset of token to replace in zOut */
- RenameToken *pBest = renameColumnTokenNext(pRename);
-
u32 nReplace;
const char *zReplace;
- if( sqlcipher_sqlite3IsIdChar(*pBest->t.z) ){
- nReplace = nNew;
- zReplace = zNew;
+ RenameToken *pBest = renameColumnTokenNext(pRename);
+
+ if( zNew ){
+ if( bQuote==0 && sqlcipher_sqlite3IsIdChar(*pBest->t.z) ){
+ nReplace = nNew;
+ zReplace = zNew;
+ }else{
+ nReplace = nQuot;
+ zReplace = zQuot;
+ if( pBest->t.z[pBest->t.n]=='"' ) nReplace++;
+ }
}else{
- nReplace = nQuot;
- zReplace = zQuot;
+ /* Dequote the double-quoted token. Then requote it again, this time
+ ** using single quotes. If the character immediately following the
+ ** original token within the input SQL was a single quote ('), then
+ ** add another space after the new, single-quoted version of the
+ ** token. This is so that (SELECT "string"'alias') maps to
+ ** (SELECT 'string' 'alias'), and not (SELECT 'string''alias'). */
+ memcpy(zBuf1, pBest->t.z, pBest->t.n);
+ zBuf1[pBest->t.n] = 0;
+ sqlcipher_sqlite3Dequote(zBuf1);
+ sqlcipher_sqlite3_snprintf(nSql*2, zBuf2, "%Q%s", zBuf1,
+ pBest->t.z[pBest->t.n]=='\'' ? " " : ""
+ );
+ zReplace = zBuf2;
+ nReplace = sqlcipher_sqlite3Strlen30(zReplace);
}
iOff = pBest->t.z - zSql;
@@ -112162,26 +116598,35 @@ static int renameResolveTrigger(Parse *pParse){
if( rc==SQLITE_OK && pStep->zTarget ){
SrcList *pSrc = sqlcipher_sqlite3TriggerStepSrc(pParse, pStep);
if( pSrc ){
- int i;
- for(i=0; i<pSrc->nSrc && rc==SQLITE_OK; i++){
- struct SrcList_item *p = &pSrc->a[i];
- p->iCursor = pParse->nTab++;
- if( p->pSelect ){
- sqlcipher_sqlite3SelectPrep(pParse, p->pSelect, 0);
- sqlcipher_sqlite3ExpandSubquery(pParse, p);
- assert( i>0 );
- assert( pStep->pFrom->a[i-1].pSelect );
- sqlcipher_sqlite3SelectPrep(pParse, pStep->pFrom->a[i-1].pSelect, 0);
- }else{
- p->pTab = sqlcipher_sqlite3LocateTableItem(pParse, 0, p);
- if( p->pTab==0 ){
- rc = SQLITE_ERROR;
- }else{
- p->pTab->nTabRef++;
- rc = sqlcipher_sqlite3ViewGetColumnNames(pParse, p->pTab);
+ Select *pSel = sqlcipher_sqlite3SelectNew(
+ pParse, pStep->pExprList, pSrc, 0, 0, 0, 0, 0, 0
+ );
+ if( pSel==0 ){
+ pStep->pExprList = 0;
+ pSrc = 0;
+ rc = SQLITE_NOMEM;
+ }else{
+ sqlcipher_sqlite3SelectPrep(pParse, pSel, 0);
+ rc = pParse->nErr ? SQLITE_ERROR : SQLITE_OK;
+ assert( pStep->pExprList==0 || pStep->pExprList==pSel->pEList );
+ assert( pSrc==pSel->pSrc );
+ if( pStep->pExprList ) pSel->pEList = 0;
+ pSel->pSrc = 0;
+ sqlcipher_sqlite3SelectDelete(db, pSel);
+ }
+ if( pStep->pFrom ){
+ int i;
+ for(i=0; i<pStep->pFrom->nSrc && rc==SQLITE_OK; i++){
+ SrcItem *p = &pStep->pFrom->a[i];
+ if( p->pSelect ){
+ sqlcipher_sqlite3SelectPrep(pParse, p->pSelect, 0);
}
}
}
+
+ if( db->mallocFailed ){
+ rc = SQLITE_NOMEM;
+ }
sNC.pSrcList = pSrc;
if( rc==SQLITE_OK && pStep->pWhere ){
rc = sqlcipher_sqlite3ResolveExprNames(&sNC, pStep->pWhere);
@@ -112190,9 +116635,8 @@ static int renameResolveTrigger(Parse *pParse){
rc = sqlcipher_sqlite3ResolveExprListNames(&sNC, pStep->pExprList);
}
assert( !pStep->pUpsert || (!pStep->pWhere && !pStep->pExprList) );
- if( pStep->pUpsert ){
+ if( pStep->pUpsert && rc==SQLITE_OK ){
Upsert *pUpsert = pStep->pUpsert;
- assert( rc==SQLITE_OK );
pUpsert->pUpsertSrc = pSrc;
sNC.uNC.pUpsert = pUpsert;
sNC.ncFlags = NC_UUpsert;
@@ -112268,13 +116712,13 @@ static void renameParseCleanup(Parse *pParse){
sqlcipher_sqlite3DeleteTrigger(db, pParse->pNewTrigger);
sqlcipher_sqlite3DbFree(db, pParse->zErrMsg);
renameTokenFree(db, pParse->pRename);
- sqlcipher_sqlite3ParserReset(pParse);
+ sqlcipher_sqlite3ParseObjectReset(pParse);
}
/*
** SQL function:
**
-** sqlite_rename_column(zSql, iCol, bQuote, zNew, zTable, zOld)
+** sqlite_rename_column(SQL,TYPE,OBJ,DB,TABLE,COL,NEWNAME,QUOTE,TEMP)
**
** 0. zSql: SQL statement to rewrite
** 1. type: Type of object ("table", "view" etc.)
@@ -112292,7 +116736,8 @@ static void renameParseCleanup(Parse *pParse){
**
** This function is used internally by the ALTER TABLE RENAME COLUMN command.
** It is only accessible to SQL created using sqlcipher_sqlite3NestedParse(). It is
-** not reachable from ordinary SQL passed into sqlcipher_sqlite3_prepare().
+** not reachable from ordinary SQL passed into sqlcipher_sqlite3_prepare() unless the
+** SQLITE_TESTCTRL_INTERNAL_FUNCTIONS test setting is enabled.
*/
static void renameColumnFunc(
sqlcipher_sqlite3_context *context,
@@ -112330,7 +116775,7 @@ static void renameColumnFunc(
sqlcipher_sqlite3BtreeLeaveAll(db);
return;
}
- zOld = pTab->aCol[iCol].zName;
+ zOld = pTab->aCol[iCol].zCnName;
memset(&sCtx, 0, sizeof(sCtx));
sCtx.iCol = ((iCol==pTab->iPKey) ? -1 : iCol);
@@ -112349,8 +116794,8 @@ static void renameColumnFunc(
sCtx.pTab = pTab;
if( rc!=SQLITE_OK ) goto renameColumnFunc_done;
if( sParse.pNewTable ){
- Select *pSelect = sParse.pNewTable->pSelect;
- if( pSelect ){
+ if( IsView(sParse.pNewTable) ){
+ Select *pSelect = sParse.pNewTable->u.view.pSelect;
pSelect->selFlags &= ~SF_View;
sParse.rc = SQLITE_OK;
sqlcipher_sqlite3SelectPrep(&sParse, pSelect, 0);
@@ -112359,16 +116804,17 @@ static void renameColumnFunc(
sqlcipher_sqlite3WalkSelect(&sWalker, pSelect);
}
if( rc!=SQLITE_OK ) goto renameColumnFunc_done;
- }else{
+ }else if( IsOrdinaryTable(sParse.pNewTable) ){
/* A regular table */
int bFKOnly = sqlcipher_sqlite3_stricmp(zTable, sParse.pNewTable->zName);
FKey *pFKey;
- assert( sParse.pNewTable->pSelect==0 );
sCtx.pTab = sParse.pNewTable;
if( bFKOnly==0 ){
- renameTokenFind(
- &sParse, &sCtx, (void*)sParse.pNewTable->aCol[iCol].zName
- );
+ if( iCol<sParse.pNewTable->nCol ){
+ renameTokenFind(
+ &sParse, &sCtx, (void*)sParse.pNewTable->aCol[iCol].zCnName
+ );
+ }
if( sCtx.iCol<0 ){
renameTokenFind(&sParse, &sCtx, (void*)&sParse.pNewTable->iPKey);
}
@@ -112379,14 +116825,17 @@ static void renameColumnFunc(
for(pIdx=sParse.pNewIndex; pIdx; pIdx=pIdx->pNext){
sqlcipher_sqlite3WalkExprList(&sWalker, pIdx->aColExpr);
}
- }
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
- for(i=0; i<sParse.pNewTable->nCol; i++){
- sqlcipher_sqlite3WalkExpr(&sWalker, sParse.pNewTable->aCol[i].pDflt);
- }
+ for(i=0; i<sParse.pNewTable->nCol; i++){
+ Expr *pExpr = sqlcipher_sqlite3ColumnExpr(sParse.pNewTable,
+ &sParse.pNewTable->aCol[i]);
+ sqlcipher_sqlite3WalkExpr(&sWalker, pExpr);
+ }
#endif
+ }
- for(pFKey=sParse.pNewTable->pFKey; pFKey; pFKey=pFKey->pNextFrom){
+ assert( IsOrdinaryTable(sParse.pNewTable) );
+ for(pFKey=sParse.pNewTable->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){
for(i=0; i<pFKey->nCol; i++){
if( bFKOnly==0 && pFKey->aCol[i].iFrom==iCol ){
renameTokenFind(&sParse, &sCtx, (void*)&pFKey->aCol[i]);
@@ -112437,8 +116886,10 @@ static void renameColumnFunc(
renameColumnFunc_done:
if( rc!=SQLITE_OK ){
- if( sParse.zErrMsg ){
- renameColumnParseError(context, 0, argv[1], argv[2], &sParse);
+ if( rc==SQLITE_ERROR && sqlcipher_sqlite3WritableSchema(db) ){
+ sqlcipher_sqlite3_result_value(context, argv[0]);
+ }else if( sParse.zErrMsg ){
+ renameColumnParseError(context, "", argv[1], argv[2], &sParse);
}else{
sqlcipher_sqlite3_result_error_code(context, rc);
}
@@ -112457,7 +116908,10 @@ renameColumnFunc_done:
*/
static int renameTableExprCb(Walker *pWalker, Expr *pExpr){
RenameCtx *p = pWalker->u.pRename;
- if( pExpr->op==TK_COLUMN && p->pTab==pExpr->y.pTab ){
+ if( pExpr->op==TK_COLUMN
+ && ALWAYS(ExprUseYTab(pExpr))
+ && p->pTab==pExpr->y.pTab
+ ){
renameTokenFind(pWalker->pParse, p, (void*)&pExpr->y.pTab);
}
return WRC_Continue;
@@ -112470,13 +116924,17 @@ static int renameTableSelectCb(Walker *pWalker, Select *pSelect){
int i;
RenameCtx *p = pWalker->u.pRename;
SrcList *pSrc = pSelect->pSrc;
- if( pSelect->selFlags & SF_View ) return WRC_Prune;
- if( pSrc==0 ){
+ if( pSelect->selFlags & (SF_View|SF_CopyCte) ){
+ testcase( pSelect->selFlags & SF_View );
+ testcase( pSelect->selFlags & SF_CopyCte );
+ return WRC_Prune;
+ }
+ if( NEVER(pSrc==0) ){
assert( pWalker->pParse->db->mallocFailed );
return WRC_Abort;
}
for(i=0; i<pSrc->nSrc; i++){
- struct SrcList_item *pItem = &pSrc->a[i];
+ SrcItem *pItem = &pSrc->a[i];
if( pItem->pTab==p->pTab ){
renameTokenFind(pWalker->pParse, p, pItem->zName);
}
@@ -112548,28 +117006,31 @@ static void renameTableFunc(
if( sParse.pNewTable ){
Table *pTab = sParse.pNewTable;
- if( pTab->pSelect ){
+ if( IsView(pTab) ){
if( isLegacy==0 ){
- Select *pSelect = pTab->pSelect;
+ Select *pSelect = pTab->u.view.pSelect;
NameContext sNC;
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = &sParse;
assert( pSelect->selFlags & SF_View );
pSelect->selFlags &= ~SF_View;
- sqlcipher_sqlite3SelectPrep(&sParse, pTab->pSelect, &sNC);
+ sqlcipher_sqlite3SelectPrep(&sParse, pTab->u.view.pSelect, &sNC);
if( sParse.nErr ){
rc = sParse.rc;
}else{
- sqlcipher_sqlite3WalkSelect(&sWalker, pTab->pSelect);
+ sqlcipher_sqlite3WalkSelect(&sWalker, pTab->u.view.pSelect);
}
}
}else{
/* Modify any FK definitions to point to the new table. */
#ifndef SQLITE_OMIT_FOREIGN_KEY
- if( isLegacy==0 || (db->flags & SQLITE_ForeignKeys) ){
+ if( (isLegacy==0 || (db->flags & SQLITE_ForeignKeys))
+ && !IsVirtual(pTab)
+ ){
FKey *pFKey;
- for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){
+ assert( IsOrdinaryTable(pTab) );
+ for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){
if( sqlcipher_sqlite3_stricmp(pFKey->zTo, zOld)==0 ){
renameTokenFind(&sParse, &sCtx, (void*)pFKey->zTo);
}
@@ -112615,6 +117076,15 @@ static void renameTableFunc(
if( pStep->zTarget && 0==sqlcipher_sqlite3_stricmp(pStep->zTarget, zOld) ){
renameTokenFind(&sParse, &sCtx, pStep->zTarget);
}
+ if( pStep->pFrom ){
+ int i;
+ for(i=0; i<pStep->pFrom->nSrc; i++){
+ SrcItem *pItem = &pStep->pFrom->a[i];
+ if( 0==sqlcipher_sqlite3_stricmp(pItem->zName, zOld) ){
+ renameTokenFind(&sParse, &sCtx, pItem->zName);
+ }
+ }
+ }
}
}
}
@@ -112626,8 +117096,10 @@ static void renameTableFunc(
rc = renameEditSql(context, &sCtx, zInput, zNew, bQuote);
}
if( rc!=SQLITE_OK ){
- if( sParse.zErrMsg ){
- renameColumnParseError(context, 0, argv[1], argv[2], &sParse);
+ if( rc==SQLITE_ERROR && sqlcipher_sqlite3WritableSchema(db) ){
+ sqlcipher_sqlite3_result_value(context, argv[3]);
+ }else if( sParse.zErrMsg ){
+ renameColumnParseError(context, "", argv[1], argv[2], &sParse);
}else{
sqlcipher_sqlite3_result_error_code(context, rc);
}
@@ -112644,7 +117116,131 @@ static void renameTableFunc(
return;
}
-/*
+static int renameQuotefixExprCb(Walker *pWalker, Expr *pExpr){
+ if( pExpr->op==TK_STRING && (pExpr->flags & EP_DblQuoted) ){
+ renameTokenFind(pWalker->pParse, pWalker->u.pRename, (const void*)pExpr);
+ }
+ return WRC_Continue;
+}
+
+/* SQL function: sqlite_rename_quotefix(DB,SQL)
+**
+** Rewrite the DDL statement "SQL" so that any string literals that use
+** double-quotes use single quotes instead.
+**
+** Two arguments must be passed:
+**
+** 0: Database name ("main", "temp" etc.).
+** 1: SQL statement to edit.
+**
+** The returned value is the modified SQL statement. For example, given
+** the database schema:
+**
+** CREATE TABLE t1(a, b, c);
+**
+** SELECT sqlite_rename_quotefix('main',
+** 'CREATE VIEW v1 AS SELECT "a", "string" FROM t1'
+** );
+**
+** returns the string:
+**
+** CREATE VIEW v1 AS SELECT "a", 'string' FROM t1
+**
+** If there is a error in the input SQL, then raise an error, except
+** if PRAGMA writable_schema=ON, then just return the input string
+** unmodified following an error.
+*/
+static void renameQuotefixFunc(
+ sqlcipher_sqlite3_context *context,
+ int NotUsed,
+ sqlcipher_sqlite3_value **argv
+){
+ sqlcipher_sqlite3 *db = sqlcipher_sqlite3_context_db_handle(context);
+ char const *zDb = (const char*)sqlcipher_sqlite3_value_text(argv[0]);
+ char const *zInput = (const char*)sqlcipher_sqlite3_value_text(argv[1]);
+
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ sqlcipher_sqlite3_xauth xAuth = db->xAuth;
+ db->xAuth = 0;
+#endif
+
+ sqlcipher_sqlite3BtreeEnterAll(db);
+
+ UNUSED_PARAMETER(NotUsed);
+ if( zDb && zInput ){
+ int rc;
+ Parse sParse;
+ rc = renameParseSql(&sParse, zDb, db, zInput, 0);
+
+ if( rc==SQLITE_OK ){
+ RenameCtx sCtx;
+ Walker sWalker;
+
+ /* Walker to find tokens that need to be replaced. */
+ memset(&sCtx, 0, sizeof(RenameCtx));
+ memset(&sWalker, 0, sizeof(Walker));
+ sWalker.pParse = &sParse;
+ sWalker.xExprCallback = renameQuotefixExprCb;
+ sWalker.xSelectCallback = renameColumnSelectCb;
+ sWalker.u.pRename = &sCtx;
+
+ if( sParse.pNewTable ){
+ if( IsView(sParse.pNewTable) ){
+ Select *pSelect = sParse.pNewTable->u.view.pSelect;
+ pSelect->selFlags &= ~SF_View;
+ sParse.rc = SQLITE_OK;
+ sqlcipher_sqlite3SelectPrep(&sParse, pSelect, 0);
+ rc = (db->mallocFailed ? SQLITE_NOMEM : sParse.rc);
+ if( rc==SQLITE_OK ){
+ sqlcipher_sqlite3WalkSelect(&sWalker, pSelect);
+ }
+ }else{
+ int i;
+ sqlcipher_sqlite3WalkExprList(&sWalker, sParse.pNewTable->pCheck);
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
+ for(i=0; i<sParse.pNewTable->nCol; i++){
+ sqlcipher_sqlite3WalkExpr(&sWalker,
+ sqlcipher_sqlite3ColumnExpr(sParse.pNewTable,
+ &sParse.pNewTable->aCol[i]));
+ }
+#endif /* SQLITE_OMIT_GENERATED_COLUMNS */
+ }
+ }else if( sParse.pNewIndex ){
+ sqlcipher_sqlite3WalkExprList(&sWalker, sParse.pNewIndex->aColExpr);
+ sqlcipher_sqlite3WalkExpr(&sWalker, sParse.pNewIndex->pPartIdxWhere);
+ }else{
+#ifndef SQLITE_OMIT_TRIGGER
+ rc = renameResolveTrigger(&sParse);
+ if( rc==SQLITE_OK ){
+ renameWalkTrigger(&sWalker, sParse.pNewTrigger);
+ }
+#endif /* SQLITE_OMIT_TRIGGER */
+ }
+
+ if( rc==SQLITE_OK ){
+ rc = renameEditSql(context, &sCtx, zInput, 0, 0);
+ }
+ renameTokenFree(db, sCtx.pList);
+ }
+ if( rc!=SQLITE_OK ){
+ if( sqlcipher_sqlite3WritableSchema(db) && rc==SQLITE_ERROR ){
+ sqlcipher_sqlite3_result_value(context, argv[1]);
+ }else{
+ sqlcipher_sqlite3_result_error_code(context, rc);
+ }
+ }
+ renameParseCleanup(&sParse);
+ }
+
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ db->xAuth = xAuth;
+#endif
+
+ sqlcipher_sqlite3BtreeLeaveAll(db);
+}
+
+/* Function: sqlite_rename_test(DB,SQL,TYPE,NAME,ISTEMP,WHEN,DQS)
+**
** An SQL user function that checks that there are no parse or symbol
** resolution problems in a CREATE TRIGGER|TABLE|VIEW|INDEX statement.
** After an ALTER TABLE .. RENAME operation is performed and the schema
@@ -112656,12 +117252,16 @@ static void renameTableFunc(
** 2: Object type ("view", "table", "trigger" or "index").
** 3: Object name.
** 4: True if object is from temp schema.
+** 5: "when" part of error message.
+** 6: True to disable the DQS quirk when parsing SQL.
**
-** Unless it finds an error, this function normally returns NULL. However, it
-** returns integer value 1 if:
+** The return value is computed as follows:
**
-** * the SQL argument creates a trigger, and
-** * the table that the trigger is attached to is in database zDb.
+** A. If an error is seen and not in PRAGMA writable_schema=ON mode,
+** then raise the error.
+** B. Else if a trigger is created and the the table that the trigger is
+** attached to is in database zDb, then return 1.
+** C. Otherwise return NULL.
*/
static void renameTableTest(
sqlcipher_sqlite3_context *context,
@@ -112673,6 +117273,8 @@ static void renameTableTest(
char const *zInput = (const char*)sqlcipher_sqlite3_value_text(argv[1]);
int bTemp = sqlcipher_sqlite3_value_int(argv[4]);
int isLegacy = (db->flags & SQLITE_LegacyAlter);
+ char const *zWhen = (const char*)sqlcipher_sqlite3_value_text(argv[5]);
+ int bNoDQS = sqlcipher_sqlite3_value_int(argv[6]);
#ifndef SQLITE_OMIT_AUTHORIZATION
sqlcipher_sqlite3_xauth xAuth = db->xAuth;
@@ -112680,16 +117282,20 @@ static void renameTableTest(
#endif
UNUSED_PARAMETER(NotUsed);
+
if( zDb && zInput ){
int rc;
Parse sParse;
+ int flags = db->flags;
+ if( bNoDQS ) db->flags &= ~(SQLITE_DqsDML|SQLITE_DqsDDL);
rc = renameParseSql(&sParse, zDb, db, zInput, bTemp);
+ db->flags |= (flags & (SQLITE_DqsDML|SQLITE_DqsDDL));
if( rc==SQLITE_OK ){
- if( isLegacy==0 && sParse.pNewTable && sParse.pNewTable->pSelect ){
+ if( isLegacy==0 && sParse.pNewTable && IsView(sParse.pNewTable) ){
NameContext sNC;
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = &sParse;
- sqlcipher_sqlite3SelectPrep(&sParse, sParse.pNewTable->pSelect, &sNC);
+ sqlcipher_sqlite3SelectPrep(&sParse, sParse.pNewTable->u.view.pSelect, &sNC);
if( sParse.nErr ) rc = sParse.rc;
}
@@ -112700,13 +117306,17 @@ static void renameTableTest(
if( rc==SQLITE_OK ){
int i1 = sqlcipher_sqlite3SchemaToIndex(db, sParse.pNewTrigger->pTabSchema);
int i2 = sqlcipher_sqlite3FindDbName(db, zDb);
- if( i1==i2 ) sqlcipher_sqlite3_result_int(context, 1);
+ if( i1==i2 ){
+ /* Handle output case B */
+ sqlcipher_sqlite3_result_int(context, 1);
+ }
}
}
}
- if( rc!=SQLITE_OK ){
- renameColumnParseError(context, 1, argv[2], argv[3], &sParse);
+ if( rc!=SQLITE_OK && zWhen && !sqlcipher_sqlite3WritableSchema(db) ){
+ /* Output case A */
+ renameColumnParseError(context, zWhen, argv[2], argv[3],&sParse);
}
renameParseCleanup(&sParse);
}
@@ -112717,13 +117327,231 @@ static void renameTableTest(
}
/*
+** The implementation of internal UDF sqlite_drop_column().
+**
+** Arguments:
+**
+** argv[0]: An integer - the index of the schema containing the table
+** argv[1]: CREATE TABLE statement to modify.
+** argv[2]: An integer - the index of the column to remove.
+**
+** The value returned is a string containing the CREATE TABLE statement
+** with column argv[2] removed.
+*/
+static void dropColumnFunc(
+ sqlcipher_sqlite3_context *context,
+ int NotUsed,
+ sqlcipher_sqlite3_value **argv
+){
+ sqlcipher_sqlite3 *db = sqlcipher_sqlite3_context_db_handle(context);
+ int iSchema = sqlcipher_sqlite3_value_int(argv[0]);
+ const char *zSql = (const char*)sqlcipher_sqlite3_value_text(argv[1]);
+ int iCol = sqlcipher_sqlite3_value_int(argv[2]);
+ const char *zDb = db->aDb[iSchema].zDbSName;
+ int rc;
+ Parse sParse;
+ RenameToken *pCol;
+ Table *pTab;
+ const char *zEnd;
+ char *zNew = 0;
+
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ sqlcipher_sqlite3_xauth xAuth = db->xAuth;
+ db->xAuth = 0;
+#endif
+
+ UNUSED_PARAMETER(NotUsed);
+ rc = renameParseSql(&sParse, zDb, db, zSql, iSchema==1);
+ if( rc!=SQLITE_OK ) goto drop_column_done;
+ pTab = sParse.pNewTable;
+ if( pTab==0 || pTab->nCol==1 || iCol>=pTab->nCol ){
+ /* This can happen if the sqlite_schema table is corrupt */
+ rc = SQLITE_CORRUPT_BKPT;
+ goto drop_column_done;
+ }
+
+ pCol = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol].zCnName);
+ if( iCol<pTab->nCol-1 ){
+ RenameToken *pEnd;
+ pEnd = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol+1].zCnName);
+ zEnd = (const char*)pEnd->t.z;
+ }else{
+ assert( IsOrdinaryTable(pTab) );
+ zEnd = (const char*)&zSql[pTab->u.tab.addColOffset];
+ while( ALWAYS(pCol->t.z[0]!=0) && pCol->t.z[0]!=',' ) pCol->t.z--;
+ }
+
+ zNew = sqlcipher_sqlite3MPrintf(db, "%.*s%s", pCol->t.z-zSql, zSql, zEnd);
+ sqlcipher_sqlite3_result_text(context, zNew, -1, SQLITE_TRANSIENT);
+ sqlcipher_sqlite3_free(zNew);
+
+drop_column_done:
+ renameParseCleanup(&sParse);
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ db->xAuth = xAuth;
+#endif
+ if( rc!=SQLITE_OK ){
+ sqlcipher_sqlite3_result_error_code(context, rc);
+ }
+}
+
+/*
+** This function is called by the parser upon parsing an
+**
+** ALTER TABLE pSrc DROP COLUMN pName
+**
+** statement. Argument pSrc contains the possibly qualified name of the
+** table being edited, and token pName the name of the column to drop.
+*/
+SQLITE_PRIVATE void sqlcipher_sqlite3AlterDropColumn(Parse *pParse, SrcList *pSrc, const Token *pName){
+ sqlcipher_sqlite3 *db = pParse->db; /* Database handle */
+ Table *pTab; /* Table to modify */
+ int iDb; /* Index of db containing pTab in aDb[] */
+ const char *zDb; /* Database containing pTab ("main" etc.) */
+ char *zCol = 0; /* Name of column to drop */
+ int iCol; /* Index of column zCol in pTab->aCol[] */
+
+ /* Look up the table being altered. */
+ assert( pParse->pNewTable==0 );
+ assert( sqlcipher_sqlite3BtreeHoldsAllMutexes(db) );
+ if( NEVER(db->mallocFailed) ) goto exit_drop_column;
+ pTab = sqlcipher_sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]);
+ if( !pTab ) goto exit_drop_column;
+
+ /* Make sure this is not an attempt to ALTER a view, virtual table or
+ ** system table. */
+ if( SQLITE_OK!=isAlterableTable(pParse, pTab) ) goto exit_drop_column;
+ if( SQLITE_OK!=isRealTable(pParse, pTab, 1) ) goto exit_drop_column;
+
+ /* Find the index of the column being dropped. */
+ zCol = sqlcipher_sqlite3NameFromToken(db, pName);
+ if( zCol==0 ){
+ assert( db->mallocFailed );
+ goto exit_drop_column;
+ }
+ iCol = sqlcipher_sqlite3ColumnIndex(pTab, zCol);
+ if( iCol<0 ){
+ sqlcipher_sqlite3ErrorMsg(pParse, "no such column: \"%T\"", pName);
+ goto exit_drop_column;
+ }
+
+ /* Do not allow the user to drop a PRIMARY KEY column or a column
+ ** constrained by a UNIQUE constraint. */
+ if( pTab->aCol[iCol].colFlags & (COLFLAG_PRIMKEY|COLFLAG_UNIQUE) ){
+ sqlcipher_sqlite3ErrorMsg(pParse, "cannot drop %s column: \"%s\"",
+ (pTab->aCol[iCol].colFlags&COLFLAG_PRIMKEY) ? "PRIMARY KEY" : "UNIQUE",
+ zCol
+ );
+ goto exit_drop_column;
+ }
+
+ /* Do not allow the number of columns to go to zero */
+ if( pTab->nCol<=1 ){
+ sqlcipher_sqlite3ErrorMsg(pParse, "cannot drop column \"%s\": no other columns exist",zCol);
+ goto exit_drop_column;
+ }
+
+ /* Edit the sqlite_schema table */
+ iDb = sqlcipher_sqlite3SchemaToIndex(db, pTab->pSchema);
+ assert( iDb>=0 );
+ zDb = db->aDb[iDb].zDbSName;
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ /* Invoke the authorization callback. */
+ if( sqlcipher_sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, zCol) ){
+ goto exit_drop_column;
+ }
+#endif
+ renameTestSchema(pParse, zDb, iDb==1, "", 0);
+ renameFixQuotes(pParse, zDb, iDb==1);
+ sqlcipher_sqlite3NestedParse(pParse,
+ "UPDATE \"%w\"." LEGACY_SCHEMA_TABLE " SET "
+ "sql = sqlite_drop_column(%d, sql, %d) "
+ "WHERE (type=='table' AND tbl_name=%Q COLLATE nocase)"
+ , zDb, iDb, iCol, pTab->zName
+ );
+
+ /* Drop and reload the database schema. */
+ renameReloadSchema(pParse, iDb, INITFLAG_AlterDrop);
+ renameTestSchema(pParse, zDb, iDb==1, "after drop column", 1);
+
+ /* Edit rows of table on disk */
+ if( pParse->nErr==0 && (pTab->aCol[iCol].colFlags & COLFLAG_VIRTUAL)==0 ){
+ int i;
+ int addr;
+ int reg;
+ int regRec;
+ Index *pPk = 0;
+ int nField = 0; /* Number of non-virtual columns after drop */
+ int iCur;
+ Vdbe *v = sqlcipher_sqlite3GetVdbe(pParse);
+ iCur = pParse->nTab++;
+ sqlcipher_sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenWrite);
+ addr = sqlcipher_sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v);
+ reg = ++pParse->nMem;
+ if( HasRowid(pTab) ){
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_Rowid, iCur, reg);
+ pParse->nMem += pTab->nCol;
+ }else{
+ pPk = sqlcipher_sqlite3PrimaryKeyIndex(pTab);
+ pParse->nMem += pPk->nColumn;
+ for(i=0; i<pPk->nKeyCol; i++){
+ sqlcipher_sqlite3VdbeAddOp3(v, OP_Column, iCur, i, reg+i+1);
+ }
+ nField = pPk->nKeyCol;
+ }
+ regRec = ++pParse->nMem;
+ for(i=0; i<pTab->nCol; i++){
+ if( i!=iCol && (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 ){
+ int regOut;
+ if( pPk ){
+ int iPos = sqlcipher_sqlite3TableColumnToIndex(pPk, i);
+ int iColPos = sqlcipher_sqlite3TableColumnToIndex(pPk, iCol);
+ if( iPos<pPk->nKeyCol ) continue;
+ regOut = reg+1+iPos-(iPos>iColPos);
+ }else{
+ regOut = reg+1+nField;
+ }
+ if( i==pTab->iPKey ){
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_Null, 0, regOut);
+ }else{
+ sqlcipher_sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, i, regOut);
+ }
+ nField++;
+ }
+ }
+ if( nField==0 ){
+ /* dbsqlfuzz 5f09e7bcc78b4954d06bf9f2400d7715f48d1fef */
+ pParse->nMem++;
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_Null, 0, reg+1);
+ nField = 1;
+ }
+ sqlcipher_sqlite3VdbeAddOp3(v, OP_MakeRecord, reg+1, nField, regRec);
+ if( pPk ){
+ sqlcipher_sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iCur, regRec, reg+1, pPk->nKeyCol);
+ }else{
+ sqlcipher_sqlite3VdbeAddOp3(v, OP_Insert, iCur, regRec, reg);
+ }
+ sqlcipher_sqlite3VdbeChangeP5(v, OPFLAG_SAVEPOSITION);
+
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_Next, iCur, addr+1); VdbeCoverage(v);
+ sqlcipher_sqlite3VdbeJumpHere(v, addr);
+ }
+
+exit_drop_column:
+ sqlcipher_sqlite3DbFree(db, zCol);
+ sqlcipher_sqlite3SrcListDelete(db, pSrc);
+}
+
+/*
** Register built-in functions used to help implement ALTER TABLE
*/
SQLITE_PRIVATE void sqlcipher_sqlite3AlterFunctions(void){
static FuncDef aAlterTableFuncs[] = {
- INTERNAL_FUNCTION(sqlite_rename_column, 9, renameColumnFunc),
- INTERNAL_FUNCTION(sqlite_rename_table, 7, renameTableFunc),
- INTERNAL_FUNCTION(sqlite_rename_test, 5, renameTableTest),
+ INTERNAL_FUNCTION(sqlite_rename_column, 9, renameColumnFunc),
+ INTERNAL_FUNCTION(sqlite_rename_table, 7, renameTableFunc),
+ INTERNAL_FUNCTION(sqlite_rename_test, 7, renameTableTest),
+ INTERNAL_FUNCTION(sqlite_drop_column, 3, dropColumnFunc),
+ INTERNAL_FUNCTION(sqlite_rename_quotefix,2, renameQuotefixFunc),
};
sqlcipher_sqlite3InsertBuiltinFuncs(aAlterTableFuncs, ArraySize(aAlterTableFuncs));
}
@@ -113166,7 +117994,6 @@ static void statInit(
+ sizeof(tRowcnt)*3*nColUp*(nCol+mxSample);
}
#endif
- db = sqlcipher_sqlite3_context_db_handle(context);
p = sqlcipher_sqlite3DbMallocZero(db, n);
if( p==0 ){
sqlcipher_sqlite3_result_error_nomem(context);
@@ -113581,32 +118408,29 @@ static void statGet(
** * "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:
+ ** rows, then each estimate is usually computed as:
**
** I = (K+D-1)/D
+ **
+ ** In other words, I is K/D rounded up to the next whole integer.
+ ** However, if I is between 1.0 and 1.1 (in other words if I is
+ ** close to 1.0 but just a little larger) then do not round up but
+ ** instead keep the I value at 1.0.
*/
- char *z;
- int i;
+ sqlcipher_sqlite3_str sStat; /* Text of the constructed "stat" line */
+ int i; /* Loop counter */
- char *zRet = sqlcipher_sqlite3MallocZero( (p->nKeyCol+1)*25 );
- if( zRet==0 ){
- sqlcipher_sqlite3_result_error_nomem(context);
- return;
- }
-
- sqlcipher_sqlite3_snprintf(24, zRet, "%llu",
+ sqlcipher_sqlite3StrAccumInit(&sStat, 0, 0, 0, (p->nKeyCol+1)*100);
+ sqlcipher_sqlite3_str_appendf(&sStat, "%llu",
p->nSkipAhead ? (u64)p->nEst : (u64)p->nRow);
- z = zRet + sqlcipher_sqlite3Strlen30(zRet);
for(i=0; i<p->nKeyCol; i++){
u64 nDistinct = p->current.anDLt[i] + 1;
u64 iVal = (p->nRow + nDistinct - 1) / nDistinct;
- sqlcipher_sqlite3_snprintf(24, z, " %llu", iVal);
- z += sqlcipher_sqlite3Strlen30(z);
+ if( iVal==2 && p->nRow*10 <= nDistinct*11 ) iVal = 1;
+ sqlcipher_sqlite3_str_appendf(&sStat, " %llu", iVal);
assert( p->current.anEq[i] );
}
- assert( z[0]=='\0' && z>zRet );
-
- sqlcipher_sqlite3_result_text(context, zRet, -1, sqlcipher_sqlite3_free);
+ sqlcipher_sqlite3ResultStrAccum(context, &sStat);
}
#ifdef SQLITE_ENABLE_STAT4
else if( eCall==STAT_GET_ROWID ){
@@ -113625,6 +118449,8 @@ static void statGet(
}
}else{
tRowcnt *aCnt = 0;
+ sqlcipher_sqlite3_str sStat;
+ int i;
assert( p->iGet<p->nSample );
switch( eCall ){
@@ -113636,23 +118462,12 @@ static void statGet(
break;
}
}
-
- {
- char *zRet = sqlcipher_sqlite3MallocZero(p->nCol * 25);
- if( zRet==0 ){
- sqlcipher_sqlite3_result_error_nomem(context);
- }else{
- int i;
- char *z = zRet;
- for(i=0; i<p->nCol; i++){
- sqlcipher_sqlite3_snprintf(24, z, "%llu ", (u64)aCnt[i]);
- z += sqlcipher_sqlite3Strlen30(z);
- }
- assert( z[0]=='\0' && z>zRet );
- z[-1] = '\0';
- sqlcipher_sqlite3_result_text(context, zRet, -1, sqlcipher_sqlite3_free);
- }
+ sqlcipher_sqlite3StrAccumInit(&sStat, 0, 0, 0, p->nCol*100);
+ for(i=0; i<p->nCol; i++){
+ sqlcipher_sqlite3_str_appendf(&sStat, "%llu ", (u64)aCnt[i]);
}
+ if( sStat.nChar ) sStat.nChar--;
+ sqlcipher_sqlite3ResultStrAccum(context, &sStat);
}
#endif /* SQLITE_ENABLE_STAT4 */
#ifndef SQLITE_DEBUG
@@ -113701,7 +118516,7 @@ static void analyzeVdbeCommentIndexWithColumnName(
}else if( i==XN_EXPR ){
VdbeComment((v,"%s.expr(%d)",pIdx->zName, k));
}else{
- VdbeComment((v,"%s.%s", pIdx->zName, pIdx->pTable->aCol[i].zName));
+ VdbeComment((v,"%s.%s", pIdx->zName, pIdx->pTable->aCol[i].zCnName));
}
}
#else
@@ -113748,7 +118563,7 @@ static void analyzeOneTable(
if( v==0 || NEVER(pTab==0) ){
return;
}
- if( pTab->tnum==0 ){
+ if( !IsOrdinaryTable(pTab) ){
/* Do not gather statistics on views or virtual tables */
return;
}
@@ -113775,7 +118590,7 @@ static void analyzeOneTable(
memcpy(pStat1->zName, "sqlite_stat1", 13);
pStat1->nCol = 3;
pStat1->iPKey = -1;
- sqlcipher_sqlite3VdbeAddOp4(pParse->pVdbe, OP_Noop, 0, 0, 0,(char*)pStat1,P4_DYNBLOB);
+ sqlcipher_sqlite3VdbeAddOp4(pParse->pVdbe, OP_Noop, 0, 0, 0,(char*)pStat1,P4_DYNAMIC);
}
#endif
@@ -114573,9 +119388,12 @@ static int loadStatTbl(
*/
static int loadStat4(sqlcipher_sqlite3 *db, const char *zDb){
int rc = SQLITE_OK; /* Result codes from subroutines */
+ const Table *pStat4;
assert( db->lookaside.bDisable );
- if( sqlcipher_sqlite3FindTable(db, "sqlite_stat4", zDb) ){
+ if( (pStat4 = sqlcipher_sqlite3FindTable(db, "sqlite_stat4", zDb))!=0
+ && IsOrdinaryTable(pStat4)
+ ){
rc = loadStatTbl(db,
"SELECT idx,count(*) FROM %Q.sqlite_stat4 GROUP BY idx",
"SELECT idx,neq,nlt,ndlt,sample FROM %Q.sqlite_stat4",
@@ -114612,6 +119430,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3AnalysisLoad(sqlcipher_sqlite3 *db, int iDb)
char *zSql;
int rc = SQLITE_OK;
Schema *pSchema = db->aDb[iDb].pSchema;
+ const Table *pStat1;
assert( iDb>=0 && iDb<db->nDb );
assert( db->aDb[iDb].pBt!=0 );
@@ -114634,7 +119453,9 @@ SQLITE_PRIVATE int sqlcipher_sqlite3AnalysisLoad(sqlcipher_sqlite3 *db, int iDb)
/* Load new statistics out of the sqlite_stat1 table */
sInfo.db = db;
sInfo.zDatabase = db->aDb[iDb].zDbSName;
- if( sqlcipher_sqlite3FindTable(db, "sqlite_stat1", sInfo.zDatabase)!=0 ){
+ if( (pStat1 = sqlcipher_sqlite3FindTable(db, "sqlite_stat1", sInfo.zDatabase))
+ && IsOrdinaryTable(pStat1)
+ ){
zSql = sqlcipher_sqlite3MPrintf(db,
"SELECT tbl,idx,stat FROM %Q.sqlite_stat1", sInfo.zDatabase);
if( zSql==0 ){
@@ -114774,7 +119595,7 @@ static void attachFunc(
if( zFile==0 ) zFile = "";
if( zName==0 ) zName = "";
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
# define REOPEN_AS_MEMDB(db) (db->init.reopenMemdb)
#else
# define REOPEN_AS_MEMDB(db) (0)
@@ -114880,8 +119701,8 @@ static void attachFunc(
/* BEGIN SQLCIPHER */
#ifdef SQLITE_HAS_CODEC
if( rc==SQLITE_OK ){
- extern int sqlcipher_sqlite3CodecAttach(sqlcipher_sqlite3*, int, const void*, int);
- extern void sqlcipher_sqlite3CodecGetKey(sqlcipher_sqlite3*, int, void**, int*);
+ extern int sqlcipherCodecAttach(sqlcipher_sqlite3*, int, const void*, int);
+ extern void sqlcipherCodecGetKey(sqlcipher_sqlite3*, int, void**, int*);
int nKey;
char *zKey;
int t = sqlcipher_sqlite3_value_type(argv[2]);
@@ -114896,16 +119717,16 @@ static void attachFunc(
case SQLITE_BLOB:
nKey = sqlcipher_sqlite3_value_bytes(argv[2]);
zKey = (char *)sqlcipher_sqlite3_value_blob(argv[2]);
- rc = sqlcipher_sqlite3CodecAttach(db, db->nDb-1, zKey, nKey);
+ rc = sqlcipherCodecAttach(db, db->nDb-1, zKey, nKey);
break;
case SQLITE_NULL:
/* No key specified. Use the key from URI filename, or if none,
** use the key from the main database. */
if( sqlcipher_sqlite3CodecQueryParameters(db, zName, zPath)==0 ){
- sqlcipher_sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey);
+ sqlcipherCodecGetKey(db, 0, (void**)&zKey, &nKey);
if( nKey || sqlcipher_sqlite3BtreeGetRequestedReserve(db->aDb[0].pBt)>0 ){
- rc = sqlcipher_sqlite3CodecAttach(db, db->nDb-1, zKey, nKey);
+ rc = sqlcipherCodecAttach(db, db->nDb-1, zKey, nKey);
}
}
break;
@@ -115062,17 +119883,18 @@ static void codeAttach(
sName.pParse = pParse;
if(
- SQLITE_OK!=(rc = resolveAttachExpr(&sName, pFilename)) ||
- SQLITE_OK!=(rc = resolveAttachExpr(&sName, pDbname)) ||
- SQLITE_OK!=(rc = resolveAttachExpr(&sName, pKey))
+ SQLITE_OK!=resolveAttachExpr(&sName, pFilename) ||
+ SQLITE_OK!=resolveAttachExpr(&sName, pDbname) ||
+ SQLITE_OK!=resolveAttachExpr(&sName, pKey)
){
goto attach_end;
}
#ifndef SQLITE_OMIT_AUTHORIZATION
- if( pAuthArg ){
+ if( ALWAYS(pAuthArg) ){
char *zAuthArg;
if( pAuthArg->op==TK_STRING ){
+ assert( !ExprHasProperty(pAuthArg, EP_IntValue) );
zAuthArg = pAuthArg->u.zToken;
}else{
zAuthArg = 0;
@@ -115150,6 +119972,69 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Attach(Parse *pParse, Expr *p, Expr *pDbnam
#endif /* SQLITE_OMIT_ATTACH */
/*
+** Expression callback used by sqlcipher_sqlite3FixAAAA() routines.
+*/
+static int fixExprCb(Walker *p, Expr *pExpr){
+ DbFixer *pFix = p->u.pFix;
+ if( !pFix->bTemp ) ExprSetProperty(pExpr, EP_FromDDL);
+ if( pExpr->op==TK_VARIABLE ){
+ if( pFix->pParse->db->init.busy ){
+ pExpr->op = TK_NULL;
+ }else{
+ sqlcipher_sqlite3ErrorMsg(pFix->pParse, "%s cannot use variables", pFix->zType);
+ return WRC_Abort;
+ }
+ }
+ return WRC_Continue;
+}
+
+/*
+** Select callback used by sqlcipher_sqlite3FixAAAA() routines.
+*/
+static int fixSelectCb(Walker *p, Select *pSelect){
+ DbFixer *pFix = p->u.pFix;
+ int i;
+ SrcItem *pItem;
+ sqlcipher_sqlite3 *db = pFix->pParse->db;
+ int iDb = sqlcipher_sqlite3FindDbName(db, pFix->zDb);
+ SrcList *pList = pSelect->pSrc;
+
+ if( NEVER(pList==0) ) return WRC_Continue;
+ for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
+ if( pFix->bTemp==0 ){
+ if( pItem->zDatabase ){
+ if( iDb!=sqlcipher_sqlite3FindDbName(db, pItem->zDatabase) ){
+ sqlcipher_sqlite3ErrorMsg(pFix->pParse,
+ "%s %T cannot reference objects in database %s",
+ pFix->zType, pFix->pName, pItem->zDatabase);
+ return WRC_Abort;
+ }
+ sqlcipher_sqlite3DbFree(db, pItem->zDatabase);
+ pItem->zDatabase = 0;
+ pItem->fg.notCte = 1;
+ }
+ pItem->pSchema = pFix->pSchema;
+ pItem->fg.fromDDL = 1;
+ }
+#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
+ if( pList->a[i].fg.isUsing==0
+ && sqlcipher_sqlite3WalkExpr(&pFix->w, pList->a[i].u3.pOn)
+ ){
+ return WRC_Abort;
+ }
+#endif
+ }
+ if( pSelect->pWith ){
+ for(i=0; i<pSelect->pWith->nCte; i++){
+ if( sqlcipher_sqlite3WalkSelect(p, pSelect->pWith->a[i].pSelect) ){
+ return WRC_Abort;
+ }
+ }
+ }
+ return WRC_Continue;
+}
+
+/*
** Initialize a DbFixer structure. This routine must be called prior
** to passing the structure to one of the sqliteFixAAAA() routines below.
*/
@@ -115160,9 +120045,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3FixInit(
const char *zType, /* "view", "trigger", or "index" */
const Token *pName /* Name of the view, trigger, or index */
){
- sqlcipher_sqlite3 *db;
-
- db = pParse->db;
+ sqlcipher_sqlite3 *db = pParse->db;
assert( db->nDb>iDb );
pFix->pParse = pParse;
pFix->zDb = db->aDb[iDb].zDbSName;
@@ -115170,6 +120053,13 @@ SQLITE_PRIVATE void sqlcipher_sqlite3FixInit(
pFix->zType = zType;
pFix->pName = pName;
pFix->bTemp = (iDb==1);
+ pFix->w.pParse = pParse;
+ pFix->w.xExprCallback = fixExprCb;
+ pFix->w.xSelectCallback = fixSelectCb;
+ pFix->w.xSelectCallback2 = sqlcipher_sqlite3WalkWinDefnDummyCallback;
+ pFix->w.walkerDepth = 0;
+ pFix->w.eCode = 0;
+ pFix->w.u.pFix = pFix;
}
/*
@@ -115190,115 +120080,27 @@ SQLITE_PRIVATE int sqlcipher_sqlite3FixSrcList(
DbFixer *pFix, /* Context of the fixation */
SrcList *pList /* The Source list to check and modify */
){
- int i;
- struct SrcList_item *pItem;
- sqlcipher_sqlite3 *db = pFix->pParse->db;
- int iDb = sqlcipher_sqlite3FindDbName(db, pFix->zDb);
-
- if( NEVER(pList==0) ) return 0;
-
- for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
- if( pFix->bTemp==0 ){
- if( pItem->zDatabase && iDb!=sqlcipher_sqlite3FindDbName(db, pItem->zDatabase) ){
- sqlcipher_sqlite3ErrorMsg(pFix->pParse,
- "%s %T cannot reference objects in database %s",
- pFix->zType, pFix->pName, pItem->zDatabase);
- return 1;
- }
- sqlcipher_sqlite3DbFree(db, pItem->zDatabase);
- pItem->zDatabase = 0;
- pItem->pSchema = pFix->pSchema;
- pItem->fg.fromDDL = 1;
- }
-#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
- if( sqlcipher_sqlite3FixSelect(pFix, pItem->pSelect) ) return 1;
- if( sqlcipher_sqlite3FixExpr(pFix, pItem->pOn) ) return 1;
-#endif
- if( pItem->fg.isTabFunc && sqlcipher_sqlite3FixExprList(pFix, pItem->u1.pFuncArg) ){
- return 1;
- }
+ int res = 0;
+ if( pList ){
+ Select s;
+ memset(&s, 0, sizeof(s));
+ s.pSrc = pList;
+ res = sqlcipher_sqlite3WalkSelect(&pFix->w, &s);
}
- return 0;
+ return res;
}
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
SQLITE_PRIVATE int sqlcipher_sqlite3FixSelect(
DbFixer *pFix, /* Context of the fixation */
Select *pSelect /* The SELECT statement to be fixed to one database */
){
- while( pSelect ){
- if( sqlcipher_sqlite3FixExprList(pFix, pSelect->pEList) ){
- return 1;
- }
- if( sqlcipher_sqlite3FixSrcList(pFix, pSelect->pSrc) ){
- return 1;
- }
- if( sqlcipher_sqlite3FixExpr(pFix, pSelect->pWhere) ){
- return 1;
- }
- if( sqlcipher_sqlite3FixExprList(pFix, pSelect->pGroupBy) ){
- return 1;
- }
- if( sqlcipher_sqlite3FixExpr(pFix, pSelect->pHaving) ){
- return 1;
- }
- if( sqlcipher_sqlite3FixExprList(pFix, pSelect->pOrderBy) ){
- return 1;
- }
- if( sqlcipher_sqlite3FixExpr(pFix, pSelect->pLimit) ){
- return 1;
- }
- if( pSelect->pWith ){
- int i;
- for(i=0; i<pSelect->pWith->nCte; i++){
- if( sqlcipher_sqlite3FixSelect(pFix, pSelect->pWith->a[i].pSelect) ){
- return 1;
- }
- }
- }
- pSelect = pSelect->pPrior;
- }
- return 0;
+ return sqlcipher_sqlite3WalkSelect(&pFix->w, pSelect);
}
SQLITE_PRIVATE int sqlcipher_sqlite3FixExpr(
DbFixer *pFix, /* Context of the fixation */
Expr *pExpr /* The expression to be fixed to one database */
){
- while( pExpr ){
- if( !pFix->bTemp ) ExprSetProperty(pExpr, EP_FromDDL);
- if( pExpr->op==TK_VARIABLE ){
- if( pFix->pParse->db->init.busy ){
- pExpr->op = TK_NULL;
- }else{
- sqlcipher_sqlite3ErrorMsg(pFix->pParse, "%s cannot use variables", pFix->zType);
- return 1;
- }
- }
- if( ExprHasProperty(pExpr, EP_TokenOnly|EP_Leaf) ) break;
- if( ExprHasProperty(pExpr, EP_xIsSelect) ){
- if( sqlcipher_sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1;
- }else{
- if( sqlcipher_sqlite3FixExprList(pFix, pExpr->x.pList) ) return 1;
- }
- if( sqlcipher_sqlite3FixExpr(pFix, pExpr->pRight) ){
- return 1;
- }
- pExpr = pExpr->pLeft;
- }
- return 0;
-}
-SQLITE_PRIVATE int sqlcipher_sqlite3FixExprList(
- DbFixer *pFix, /* Context of the fixation */
- ExprList *pList /* The expression to be fixed to one database */
-){
- int i;
- struct ExprList_item *pItem;
- if( pList==0 ) return 0;
- for(i=0, pItem=pList->a; i<pList->nExpr; i++, pItem++){
- if( sqlcipher_sqlite3FixExpr(pFix, pItem->pExpr) ){
- return 1;
- }
- }
- return 0;
+ return sqlcipher_sqlite3WalkExpr(&pFix->w, pExpr);
}
#endif
@@ -115308,32 +120110,30 @@ SQLITE_PRIVATE int sqlcipher_sqlite3FixTriggerStep(
TriggerStep *pStep /* The trigger step be fixed to one database */
){
while( pStep ){
- if( sqlcipher_sqlite3FixSelect(pFix, pStep->pSelect) ){
- return 1;
- }
- if( sqlcipher_sqlite3FixExpr(pFix, pStep->pWhere) ){
- return 1;
- }
- if( sqlcipher_sqlite3FixExprList(pFix, pStep->pExprList) ){
- return 1;
- }
- if( pStep->pFrom && sqlcipher_sqlite3FixSrcList(pFix, pStep->pFrom) ){
+ if( sqlcipher_sqlite3WalkSelect(&pFix->w, pStep->pSelect)
+ || sqlcipher_sqlite3WalkExpr(&pFix->w, pStep->pWhere)
+ || sqlcipher_sqlite3WalkExprList(&pFix->w, pStep->pExprList)
+ || sqlcipher_sqlite3FixSrcList(pFix, pStep->pFrom)
+ ){
return 1;
}
#ifndef SQLITE_OMIT_UPSERT
- if( pStep->pUpsert ){
- Upsert *pUp = pStep->pUpsert;
- if( sqlcipher_sqlite3FixExprList(pFix, pUp->pUpsertTarget)
- || sqlcipher_sqlite3FixExpr(pFix, pUp->pUpsertTargetWhere)
- || sqlcipher_sqlite3FixExprList(pFix, pUp->pUpsertSet)
- || sqlcipher_sqlite3FixExpr(pFix, pUp->pUpsertWhere)
- ){
- return 1;
+ {
+ Upsert *pUp;
+ for(pUp=pStep->pUpsert; pUp; pUp=pUp->pNextUpsert){
+ if( sqlcipher_sqlite3WalkExprList(&pFix->w, pUp->pUpsertTarget)
+ || sqlcipher_sqlite3WalkExpr(&pFix->w, pUp->pUpsertTargetWhere)
+ || sqlcipher_sqlite3WalkExprList(&pFix->w, pUp->pUpsertSet)
+ || sqlcipher_sqlite3WalkExpr(&pFix->w, pUp->pUpsertWhere)
+ ){
+ return 1;
+ }
}
}
#endif
pStep = pStep->pNext;
}
+
return 0;
}
#endif
@@ -115485,7 +120285,6 @@ SQLITE_PRIVATE void sqlcipher_sqlite3AuthRead(
Schema *pSchema, /* The schema of the expression */
SrcList *pTabList /* All table that pExpr might refer to */
){
- sqlcipher_sqlite3 *db = pParse->db;
Table *pTab = 0; /* The table being read */
const char *zCol; /* Name of the column of the table */
int iSrc; /* Index in pTabList->a[] of table being read */
@@ -115493,8 +120292,8 @@ SQLITE_PRIVATE void sqlcipher_sqlite3AuthRead(
int iCol; /* Index of column in table */
assert( pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER );
- assert( !IN_RENAME_OBJECT || db->xAuth==0 );
- if( db->xAuth==0 ) return;
+ assert( !IN_RENAME_OBJECT );
+ assert( pParse->db->xAuth!=0 );
iDb = sqlcipher_sqlite3SchemaToIndex(pParse->db, pSchema);
if( iDb<0 ){
/* An attempt to read a column out of a subquery or other
@@ -115506,7 +120305,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3AuthRead(
pTab = pParse->pTriggerTab;
}else{
assert( pTabList );
- for(iSrc=0; ALWAYS(iSrc<pTabList->nSrc); iSrc++){
+ for(iSrc=0; iSrc<pTabList->nSrc; iSrc++){
if( pExpr->iTable==pTabList->a[iSrc].iCursor ){
pTab = pTabList->a[iSrc].pTab;
break;
@@ -115514,18 +120313,18 @@ SQLITE_PRIVATE void sqlcipher_sqlite3AuthRead(
}
}
iCol = pExpr->iColumn;
- if( NEVER(pTab==0) ) return;
+ if( pTab==0 ) return;
if( iCol>=0 ){
assert( iCol<pTab->nCol );
- zCol = pTab->aCol[iCol].zName;
+ zCol = pTab->aCol[iCol].zCnName;
}else if( pTab->iPKey>=0 ){
assert( pTab->iPKey<pTab->nCol );
- zCol = pTab->aCol[pTab->iPKey].zName;
+ zCol = pTab->aCol[pTab->iPKey].zCnName;
}else{
zCol = "ROWID";
}
- assert( iDb>=0 && iDb<db->nDb );
+ assert( iDb>=0 && iDb<pParse->db->nDb );
if( SQLITE_IGNORE==sqlcipher_sqlite3AuthReadCol(pParse, pTab->zName, zCol, iDb) ){
pExpr->op = TK_NULL;
}
@@ -115551,11 +120350,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3AuthCheck(
** or if the parser is being invoked from within sqlcipher_sqlite3_declare_vtab.
*/
assert( !IN_RENAME_OBJECT || db->xAuth==0 );
- if( db->init.busy || IN_SPECIAL_PARSE ){
- return SQLITE_OK;
- }
-
- if( db->xAuth==0 ){
+ if( db->xAuth==0 || db->init.busy || IN_SPECIAL_PARSE ){
return SQLITE_OK;
}
@@ -115664,7 +120459,7 @@ struct TableLock {
** code to make the lock occur is generated by a later call to
** codeTableLocks() which occurs during sqlcipher_sqlite3FinishCoding().
*/
-SQLITE_PRIVATE void sqlcipher_sqlite3TableLock(
+static SQLITE_NOINLINE void lockTable(
Parse *pParse, /* Parsing context */
int iDb, /* Index of the database containing the table to lock */
Pgno iTab, /* Root page number of the table to be locked */
@@ -115677,8 +120472,6 @@ SQLITE_PRIVATE void sqlcipher_sqlite3TableLock(
TableLock *p;
assert( iDb>=0 );
- if( iDb==1 ) return;
- if( !sqlcipher_sqlite3BtreeSharable(pParse->db->aDb[iDb].pBt) ) return;
pToplevel = sqlcipher_sqlite3ParseToplevel(pParse);
for(i=0; i<pToplevel->nTableLock; i++){
p = &pToplevel->aTableLock[i];
@@ -115702,6 +120495,17 @@ SQLITE_PRIVATE void sqlcipher_sqlite3TableLock(
sqlcipher_sqlite3OomFault(pToplevel->db);
}
}
+SQLITE_PRIVATE void sqlcipher_sqlite3TableLock(
+ Parse *pParse, /* Parsing context */
+ int iDb, /* Index of the database containing the table to lock */
+ Pgno iTab, /* Root page number of the table to be locked */
+ u8 isWriteLock, /* True for a write lock */
+ const char *zName /* Name of the table to be locked */
+){
+ if( iDb==1 ) return;
+ if( !sqlcipher_sqlite3BtreeSharable(pParse->db->aDb[iDb].pBt) ) return;
+ lockTable(pParse, iDb, iTab, isWriteLock, zName);
+}
/*
** Code an OP_TableLock instruction for each table locked by the
@@ -115752,19 +120556,50 @@ SQLITE_PRIVATE void sqlcipher_sqlite3FinishCoding(Parse *pParse){
assert( pParse->pToplevel==0 );
db = pParse->db;
+ assert( db->pParse==pParse );
if( pParse->nested ) return;
- if( db->mallocFailed || pParse->nErr ){
- if( pParse->rc==SQLITE_OK ) pParse->rc = SQLITE_ERROR;
+ if( pParse->nErr ){
+ if( db->mallocFailed ) pParse->rc = SQLITE_NOMEM;
return;
}
+ assert( db->mallocFailed==0 );
/* Begin by generating some termination code at the end of the
** vdbe program
*/
- v = sqlcipher_sqlite3GetVdbe(pParse);
+ v = pParse->pVdbe;
+ if( v==0 ){
+ if( db->init.busy ){
+ pParse->rc = SQLITE_DONE;
+ return;
+ }
+ v = sqlcipher_sqlite3GetVdbe(pParse);
+ if( v==0 ) pParse->rc = SQLITE_ERROR;
+ }
assert( !pParse->isMultiWrite
|| sqlcipher_sqlite3VdbeAssertMayAbort(v, pParse->mayAbort));
if( v ){
+ if( pParse->bReturning ){
+ Returning *pReturning = pParse->u1.pReturning;
+ int addrRewind;
+ int i;
+ int reg;
+
+ if( pReturning->nRetCol ){
+ sqlcipher_sqlite3VdbeAddOp0(v, OP_FkCheck);
+ addrRewind =
+ sqlcipher_sqlite3VdbeAddOp1(v, OP_Rewind, pReturning->iRetCur);
+ VdbeCoverage(v);
+ reg = pReturning->iRetReg;
+ for(i=0; i<pReturning->nRetCol; i++){
+ sqlcipher_sqlite3VdbeAddOp3(v, OP_Column, pReturning->iRetCur, i, reg+i);
+ }
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_ResultRow, reg, i);
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_Next, pReturning->iRetCur, addrRewind+1);
+ VdbeCoverage(v);
+ sqlcipher_sqlite3VdbeJumpHere(v, addrRewind);
+ }
+ }
sqlcipher_sqlite3VdbeAddOp0(v, OP_Halt);
#if SQLITE_USER_AUTHENTICATION
@@ -115790,7 +120625,9 @@ SQLITE_PRIVATE void sqlcipher_sqlite3FinishCoding(Parse *pParse){
int iDb, i;
assert( sqlcipher_sqlite3VdbeGetOp(v, 0)->opcode==OP_Init );
sqlcipher_sqlite3VdbeJumpHere(v, 0);
- for(iDb=0; iDb<db->nDb; iDb++){
+ assert( db->nDb>0 );
+ iDb = 0;
+ do{
Schema *pSchema;
if( DbMaskTest(pParse->cookieMask, iDb)==0 ) continue;
sqlcipher_sqlite3VdbeUsesBtree(v, iDb);
@@ -115805,7 +120642,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3FinishCoding(Parse *pParse){
if( db->init.busy==0 ) sqlcipher_sqlite3VdbeChangeP5(v, 1);
VdbeComment((v,
"usesStmtJournal=%d", pParse->mayAbort && pParse->isMultiWrite));
- }
+ }while( ++iDb<db->nDb );
#ifndef SQLITE_OMIT_VIRTUALTABLE
for(i=0; i<pParse->nVtabLock; i++){
char *vtab = (char *)sqlcipher_sqlite3GetVTable(db, pParse->apVtabLock[i]);
@@ -115842,15 +120679,23 @@ SQLITE_PRIVATE void sqlcipher_sqlite3FinishCoding(Parse *pParse){
}
}
+ if( pParse->bReturning ){
+ Returning *pRet = pParse->u1.pReturning;
+ if( pRet->nRetCol ){
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pRet->iRetCur, pRet->nRetCol);
+ }
+ }
+
/* Finally, jump back to the beginning of the executable code. */
sqlcipher_sqlite3VdbeGoto(v, 1);
}
}
-
/* Get the VDBE program ready for execution
*/
- if( v && pParse->nErr==0 && !db->mallocFailed ){
+ assert( v!=0 || pParse->nErr );
+ assert( db->mallocFailed==0 || pParse->nErr );
+ if( pParse->nErr==0 ){
/* A minimum of one cursor is required if autoincrement is used
* See ticket [a696379c1f08866] */
assert( pParse->pAinc==0 || pParse->nTab>0 );
@@ -115864,20 +120709,21 @@ SQLITE_PRIVATE void sqlcipher_sqlite3FinishCoding(Parse *pParse){
/*
** Run the parser and code generator recursively in order to generate
** code for the SQL statement given onto the end of the pParse context
-** currently under construction. When the parser is run recursively
-** this way, the final OP_Halt is not appended and other initialization
-** and finalization steps are omitted because those are handling by the
-** outermost parser.
+** currently under construction. Notes:
**
-** Not everything is nestable. This facility is designed to permit
-** INSERT, UPDATE, and DELETE operations against the schema table. Use
-** care if you decide to try to use this routine for some other purposes.
+** * The final OP_Halt is not appended and other initialization
+** and finalization steps are omitted because those are handling by the
+** outermost parser.
+**
+** * Built-in SQL functions always take precedence over application-defined
+** SQL functions. In other words, it is not possible to override a
+** built-in function.
*/
SQLITE_PRIVATE void sqlcipher_sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){
va_list ap;
char *zSql;
- char *zErrMsg = 0;
sqlcipher_sqlite3 *db = pParse->db;
+ u32 savedDbFlags = db->mDbFlags;
char saveBuf[PARSE_TAIL_SZ];
if( pParse->nErr ) return;
@@ -115896,8 +120742,9 @@ SQLITE_PRIVATE void sqlcipher_sqlite3NestedParse(Parse *pParse, const char *zFor
pParse->nested++;
memcpy(saveBuf, PARSE_TAIL(pParse), PARSE_TAIL_SZ);
memset(PARSE_TAIL(pParse), 0, PARSE_TAIL_SZ);
- sqlcipher_sqlite3RunParser(pParse, zSql, &zErrMsg);
- sqlcipher_sqlite3DbFree(db, zErrMsg);
+ db->mDbFlags |= DBFLAG_PreferBuiltin;
+ sqlcipher_sqlite3RunParser(pParse, zSql);
+ db->mDbFlags = savedDbFlags;
sqlcipher_sqlite3DbFree(db, zSql);
memcpy(PARSE_TAIL(pParse), saveBuf, PARSE_TAIL_SZ);
pParse->nested--;
@@ -115954,17 +120801,17 @@ SQLITE_PRIVATE Table *sqlcipher_sqlite3FindTable(sqlcipher_sqlite3 *db, const ch
p = sqlcipher_sqlite3HashFind(&db->aDb[i].pSchema->tblHash, zName);
if( p==0 && sqlcipher_sqlite3StrNICmp(zName, "sqlite_", 7)==0 ){
if( i==1 ){
- if( sqlcipher_sqlite3StrICmp(zName+7, &ALT_TEMP_SCHEMA_TABLE[7])==0
- || sqlcipher_sqlite3StrICmp(zName+7, &ALT_SCHEMA_TABLE[7])==0
- || sqlcipher_sqlite3StrICmp(zName+7, &DFLT_SCHEMA_TABLE[7])==0
+ if( sqlcipher_sqlite3StrICmp(zName+7, &PREFERRED_TEMP_SCHEMA_TABLE[7])==0
+ || sqlcipher_sqlite3StrICmp(zName+7, &PREFERRED_SCHEMA_TABLE[7])==0
+ || sqlcipher_sqlite3StrICmp(zName+7, &LEGACY_SCHEMA_TABLE[7])==0
){
p = sqlcipher_sqlite3HashFind(&db->aDb[1].pSchema->tblHash,
- DFLT_TEMP_SCHEMA_TABLE);
+ LEGACY_TEMP_SCHEMA_TABLE);
}
}else{
- if( sqlcipher_sqlite3StrICmp(zName+7, &ALT_SCHEMA_TABLE[7])==0 ){
+ if( sqlcipher_sqlite3StrICmp(zName+7, &PREFERRED_SCHEMA_TABLE[7])==0 ){
p = sqlcipher_sqlite3HashFind(&db->aDb[i].pSchema->tblHash,
- DFLT_SCHEMA_TABLE);
+ LEGACY_SCHEMA_TABLE);
}
}
}
@@ -115982,11 +120829,11 @@ SQLITE_PRIVATE Table *sqlcipher_sqlite3FindTable(sqlcipher_sqlite3 *db, const ch
if( p ) break;
}
if( p==0 && sqlcipher_sqlite3StrNICmp(zName, "sqlite_", 7)==0 ){
- if( sqlcipher_sqlite3StrICmp(zName+7, &ALT_SCHEMA_TABLE[7])==0 ){
- p = sqlcipher_sqlite3HashFind(&db->aDb[0].pSchema->tblHash, DFLT_SCHEMA_TABLE);
- }else if( sqlcipher_sqlite3StrICmp(zName+7, &ALT_TEMP_SCHEMA_TABLE[7])==0 ){
+ if( sqlcipher_sqlite3StrICmp(zName+7, &PREFERRED_SCHEMA_TABLE[7])==0 ){
+ p = sqlcipher_sqlite3HashFind(&db->aDb[0].pSchema->tblHash, LEGACY_SCHEMA_TABLE);
+ }else if( sqlcipher_sqlite3StrICmp(zName+7, &PREFERRED_TEMP_SCHEMA_TABLE[7])==0 ){
p = sqlcipher_sqlite3HashFind(&db->aDb[1].pSchema->tblHash,
- DFLT_TEMP_SCHEMA_TABLE);
+ LEGACY_TEMP_SCHEMA_TABLE);
}
}
}
@@ -116026,12 +120873,13 @@ SQLITE_PRIVATE Table *sqlcipher_sqlite3LocateTable(
/* If zName is the not the name of a table in the schema created using
** CREATE, then check to see if it is the name of an virtual table that
** can be an eponymous virtual table. */
- if( pParse->disableVtab==0 ){
+ if( pParse->disableVtab==0 && db->init.busy==0 ){
Module *pMod = (Module*)sqlcipher_sqlite3HashFind(&db->aModule, zName);
if( pMod==0 && sqlcipher_sqlite3_strnicmp(zName, "pragma_", 7)==0 ){
pMod = sqlcipher_sqlite3PragmaVtabRegister(db, zName);
}
if( pMod && sqlcipher_sqlite3VtabEponymousTableInit(pParse, pMod) ){
+ testcase( pMod->pEpoTab==0 );
return pMod->pEpoTab;
}
}
@@ -116049,6 +120897,8 @@ SQLITE_PRIVATE Table *sqlcipher_sqlite3LocateTable(
}else{
sqlcipher_sqlite3ErrorMsg(pParse, "%s: %s", zMsg, zName);
}
+ }else{
+ assert( HasRowid(p) || p->iPKey<0 );
}
return p;
@@ -116066,7 +120916,7 @@ SQLITE_PRIVATE Table *sqlcipher_sqlite3LocateTable(
SQLITE_PRIVATE Table *sqlcipher_sqlite3LocateTableItem(
Parse *pParse,
u32 flags,
- struct SrcList_item *p
+ SrcItem *p
){
const char *zDb;
assert( p->pSchema==0 || p->zDatabase==0 );
@@ -116080,6 +120930,22 @@ SQLITE_PRIVATE Table *sqlcipher_sqlite3LocateTableItem(
}
/*
+** Return the preferred table name for system tables. Translate legacy
+** names into the new preferred names, as appropriate.
+*/
+SQLITE_PRIVATE const char *sqlcipher_sqlite3PreferredTableName(const char *zName){
+ if( sqlcipher_sqlite3StrNICmp(zName, "sqlite_", 7)==0 ){
+ if( sqlcipher_sqlite3StrICmp(zName+7, &LEGACY_SCHEMA_TABLE[7])==0 ){
+ return PREFERRED_SCHEMA_TABLE;
+ }
+ if( sqlcipher_sqlite3StrICmp(zName+7, &LEGACY_TEMP_SCHEMA_TABLE[7])==0 ){
+ return PREFERRED_TEMP_SCHEMA_TABLE;
+ }
+ }
+ return zName;
+}
+
+/*
** Locate the in-memory structure that describes
** a particular index given the name of that index
** and the name of the database that contains the index.
@@ -116244,6 +121110,84 @@ SQLITE_PRIVATE void sqlcipher_sqlite3CommitInternalChanges(sqlcipher_sqlite3 *db
}
/*
+** Set the expression associated with a column. This is usually
+** the DEFAULT value, but might also be the expression that computes
+** the value for a generated column.
+*/
+SQLITE_PRIVATE void sqlcipher_sqlite3ColumnSetExpr(
+ Parse *pParse, /* Parsing context */
+ Table *pTab, /* The table containing the column */
+ Column *pCol, /* The column to receive the new DEFAULT expression */
+ Expr *pExpr /* The new default expression */
+){
+ ExprList *pList;
+ assert( IsOrdinaryTable(pTab) );
+ pList = pTab->u.tab.pDfltList;
+ if( pCol->iDflt==0
+ || NEVER(pList==0)
+ || NEVER(pList->nExpr<pCol->iDflt)
+ ){
+ pCol->iDflt = pList==0 ? 1 : pList->nExpr+1;
+ pTab->u.tab.pDfltList = sqlcipher_sqlite3ExprListAppend(pParse, pList, pExpr);
+ }else{
+ sqlcipher_sqlite3ExprDelete(pParse->db, pList->a[pCol->iDflt-1].pExpr);
+ pList->a[pCol->iDflt-1].pExpr = pExpr;
+ }
+}
+
+/*
+** Return the expression associated with a column. The expression might be
+** the DEFAULT clause or the AS clause of a generated column.
+** Return NULL if the column has no associated expression.
+*/
+SQLITE_PRIVATE Expr *sqlcipher_sqlite3ColumnExpr(Table *pTab, Column *pCol){
+ if( pCol->iDflt==0 ) return 0;
+ if( NEVER(!IsOrdinaryTable(pTab)) ) return 0;
+ if( NEVER(pTab->u.tab.pDfltList==0) ) return 0;
+ if( NEVER(pTab->u.tab.pDfltList->nExpr<pCol->iDflt) ) return 0;
+ return pTab->u.tab.pDfltList->a[pCol->iDflt-1].pExpr;
+}
+
+/*
+** Set the collating sequence name for a column.
+*/
+SQLITE_PRIVATE void sqlcipher_sqlite3ColumnSetColl(
+ sqlcipher_sqlite3 *db,
+ Column *pCol,
+ const char *zColl
+){
+ i64 nColl;
+ i64 n;
+ char *zNew;
+ assert( zColl!=0 );
+ n = sqlcipher_sqlite3Strlen30(pCol->zCnName) + 1;
+ if( pCol->colFlags & COLFLAG_HASTYPE ){
+ n += sqlcipher_sqlite3Strlen30(pCol->zCnName+n) + 1;
+ }
+ nColl = sqlcipher_sqlite3Strlen30(zColl) + 1;
+ zNew = sqlcipher_sqlite3DbRealloc(db, pCol->zCnName, nColl+n);
+ if( zNew ){
+ pCol->zCnName = zNew;
+ memcpy(pCol->zCnName + n, zColl, nColl);
+ pCol->colFlags |= COLFLAG_HASCOLL;
+ }
+}
+
+/*
+** Return the collating squence name for a column
+*/
+SQLITE_PRIVATE const char *sqlcipher_sqlite3ColumnColl(Column *pCol){
+ const char *z;
+ if( (pCol->colFlags & COLFLAG_HASCOLL)==0 ) return 0;
+ z = pCol->zCnName;
+ while( *z ){ z++; }
+ if( pCol->colFlags & COLFLAG_HASTYPE ){
+ do{ z++; }while( *z );
+ }
+ return z+1;
+}
+
+/*
** Delete memory allocated for the column names of a table or view (the
** Table.aCol[] array).
*/
@@ -116253,12 +121197,20 @@ SQLITE_PRIVATE void sqlcipher_sqlite3DeleteColumnNames(sqlcipher_sqlite3 *db, Ta
assert( pTable!=0 );
if( (pCol = pTable->aCol)!=0 ){
for(i=0; i<pTable->nCol; i++, pCol++){
- assert( pCol->zName==0 || pCol->hName==sqlcipher_sqlite3StrIHash(pCol->zName) );
- sqlcipher_sqlite3DbFree(db, pCol->zName);
- sqlcipher_sqlite3ExprDelete(db, pCol->pDflt);
- sqlcipher_sqlite3DbFree(db, pCol->zColl);
+ assert( pCol->zCnName==0 || pCol->hName==sqlcipher_sqlite3StrIHash(pCol->zCnName) );
+ sqlcipher_sqlite3DbFree(db, pCol->zCnName);
}
sqlcipher_sqlite3DbFree(db, pTable->aCol);
+ if( IsOrdinaryTable(pTable) ){
+ sqlcipher_sqlite3ExprListDelete(db, pTable->u.tab.pDfltList);
+ }
+ if( db==0 || db->pnBytesFreed==0 ){
+ pTable->aCol = 0;
+ pTable->nCol = 0;
+ if( IsOrdinaryTable(pTable) ){
+ pTable->u.tab.pDfltList = 0;
+ }
+ }
}
}
@@ -116310,19 +121262,25 @@ static void SQLITE_NOINLINE deleteTable(sqlcipher_sqlite3 *db, Table *pTable){
sqlcipher_sqlite3FreeIndex(db, pIndex);
}
- /* Delete any foreign keys attached to this table. */
- sqlcipher_sqlite3FkDelete(db, pTable);
+ if( IsOrdinaryTable(pTable) ){
+ sqlcipher_sqlite3FkDelete(db, pTable);
+ }
+#ifndef SQLITE_OMIT_VIRTUAL_TABLE
+ else if( IsVirtual(pTable) ){
+ sqlcipher_sqlite3VtabClear(db, pTable);
+ }
+#endif
+ else{
+ assert( IsView(pTable) );
+ sqlcipher_sqlite3SelectDelete(db, pTable->u.view.pSelect);
+ }
/* Delete the Table structure itself.
*/
sqlcipher_sqlite3DeleteColumnNames(db, pTable);
sqlcipher_sqlite3DbFree(db, pTable->zName);
sqlcipher_sqlite3DbFree(db, pTable->zColAff);
- sqlcipher_sqlite3SelectDelete(db, pTable->pSelect);
sqlcipher_sqlite3ExprListDelete(db, pTable->pCheck);
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- sqlcipher_sqlite3VtabClear(db, pTable);
-#endif
sqlcipher_sqlite3DbFree(db, pTable);
/* Verify that no lookaside memory was used by schema tables */
@@ -116368,10 +121326,10 @@ SQLITE_PRIVATE void sqlcipher_sqlite3UnlinkAndDeleteTable(sqlcipher_sqlite3 *db,
** are not \000 terminated and are not persistent. The returned string
** is \000 terminated and is persistent.
*/
-SQLITE_PRIVATE char *sqlcipher_sqlite3NameFromToken(sqlcipher_sqlite3 *db, Token *pName){
+SQLITE_PRIVATE char *sqlcipher_sqlite3NameFromToken(sqlcipher_sqlite3 *db, const Token *pName){
char *zName;
if( pName ){
- zName = sqlcipher_sqlite3DbStrNDup(db, (char*)pName->z, pName->n);
+ zName = sqlcipher_sqlite3DbStrNDup(db, (const char*)pName->z, pName->n);
sqlcipher_sqlite3Dequote(zName);
}else{
zName = 0;
@@ -116385,7 +121343,7 @@ SQLITE_PRIVATE char *sqlcipher_sqlite3NameFromToken(sqlcipher_sqlite3 *db, Token
*/
SQLITE_PRIVATE void sqlcipher_sqlite3OpenSchemaTable(Parse *p, int iDb){
Vdbe *v = sqlcipher_sqlite3GetVdbe(p);
- sqlcipher_sqlite3TableLock(p, iDb, SCHEMA_ROOT, 1, DFLT_SCHEMA_TABLE);
+ sqlcipher_sqlite3TableLock(p, iDb, SCHEMA_ROOT, 1, LEGACY_SCHEMA_TABLE);
sqlcipher_sqlite3VdbeAddOp4Int(v, OP_OpenWrite, 0, SCHEMA_ROOT, iDb, 5);
if( p->nTab==0 ){
p->nTab = 1;
@@ -116465,7 +121423,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3TwoPartName(
return -1;
}
}else{
- assert( db->init.iDb==0 || db->init.busy || IN_RENAME_OBJECT
+ assert( db->init.iDb==0 || db->init.busy || IN_SPECIAL_PARSE
|| (db->mDbFlags & DBFLAG_Vacuum)!=0);
iDb = db->init.iDb;
*pUnqual = pName1;
@@ -116635,6 +121593,23 @@ SQLITE_PRIVATE i16 sqlcipher_sqlite3TableColumnToStorage(Table *pTab, i16 iCol){
#endif
/*
+** Insert a single OP_JournalMode query opcode in order to force the
+** prepared statement to return false for sqlcipher_sqlite3_stmt_readonly(). This
+** is used by CREATE TABLE IF NOT EXISTS and similar if the table already
+** exists, so that the prepared statement for CREATE TABLE IF NOT EXISTS
+** will return false for sqlcipher_sqlite3_stmt_readonly() even if that statement
+** is a read-only no-op.
+*/
+static void sqlcipher_sqlite3ForceNotReadOnly(Parse *pParse){
+ int iReg = ++pParse->nMem;
+ Vdbe *v = sqlcipher_sqlite3GetVdbe(pParse);
+ if( v ){
+ sqlcipher_sqlite3VdbeAddOp3(v, OP_JournalMode, 0, iReg, PAGER_JOURNALMODE_QUERY);
+ sqlcipher_sqlite3VdbeUsesBtree(v, 0);
+ }
+}
+
+/*
** 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
@@ -116729,10 +121704,12 @@ SQLITE_PRIVATE void sqlcipher_sqlite3StartTable(
pTable = sqlcipher_sqlite3FindTable(db, zName, zDb);
if( pTable ){
if( !noErr ){
- sqlcipher_sqlite3ErrorMsg(pParse, "table %T already exists", pName);
+ sqlcipher_sqlite3ErrorMsg(pParse, "%s %T already exists",
+ (IsView(pTable)? "view" : "table"), pName);
}else{
assert( !db->init.busy || CORRUPT_DB );
sqlcipher_sqlite3CodeVerifySchema(pParse, iDb);
+ sqlcipher_sqlite3ForceNotReadOnly(pParse);
}
goto begin_table_error;
}
@@ -116761,17 +121738,6 @@ SQLITE_PRIVATE void sqlcipher_sqlite3StartTable(
assert( pParse->pNewTable==0 );
pParse->pNewTable = pTable;
- /* If this is the magic sqlite_sequence table used by autoincrement,
- ** then record a pointer to this table in the main database structure
- ** so that INSERT can find the table easily.
- */
-#ifndef SQLITE_OMIT_AUTOINCREMENT
- if( !pParse->nested && strcmp(zName, "sqlite_sequence")==0 ){
- assert( sqlcipher_sqlite3SchemaMutexHeld(db, iDb, 0) );
- pTable->pSchema->pSeqTab = pTable;
- }
-#endif
-
/* Begin generating the code that will insert the table record into
** the schema table. Note in particular that we must go ahead
** and allocate the record number for the table entry now. Before any
@@ -116824,7 +121790,8 @@ SQLITE_PRIVATE void sqlcipher_sqlite3StartTable(
}else
#endif
{
- pParse->addrCrTab =
+ assert( !pParse->bReturning );
+ pParse->u1.addrCrTab =
sqlcipher_sqlite3VdbeAddOp3(v, OP_CreateBtree, iDb, reg2, BTREE_INTKEY);
}
sqlcipher_sqlite3OpenSchemaTable(pParse, iDb);
@@ -116840,6 +121807,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3StartTable(
/* If an error occurs, we jump here */
begin_table_error:
+ pParse->checkSchema = 1;
sqlcipher_sqlite3DbFree(db, zName);
return;
}
@@ -116849,14 +121817,88 @@ begin_table_error:
*/
#if SQLITE_ENABLE_HIDDEN_COLUMNS
SQLITE_PRIVATE void sqlcipher_sqlite3ColumnPropertiesFromName(Table *pTab, Column *pCol){
- if( sqlcipher_sqlite3_strnicmp(pCol->zName, "__hidden__", 10)==0 ){
+ if( sqlcipher_sqlite3_strnicmp(pCol->zCnName, "__hidden__", 10)==0 ){
pCol->colFlags |= COLFLAG_HIDDEN;
+ if( pTab ) pTab->tabFlags |= TF_HasHidden;
}else if( pTab && pCol!=pTab->aCol && (pCol[-1].colFlags & COLFLAG_HIDDEN) ){
pTab->tabFlags |= TF_OOOHidden;
}
}
#endif
+/*
+** Name of the special TEMP trigger used to implement RETURNING. The
+** name begins with "sqlite_" so that it is guaranteed not to collide
+** with any application-generated triggers.
+*/
+#define RETURNING_TRIGGER_NAME "sqlite_returning"
+
+/*
+** Clean up the data structures associated with the RETURNING clause.
+*/
+static void sqlcipher_sqlite3DeleteReturning(sqlcipher_sqlite3 *db, Returning *pRet){
+ Hash *pHash;
+ pHash = &(db->aDb[1].pSchema->trigHash);
+ sqlcipher_sqlite3HashInsert(pHash, RETURNING_TRIGGER_NAME, 0);
+ sqlcipher_sqlite3ExprListDelete(db, pRet->pReturnEL);
+ sqlcipher_sqlite3DbFree(db, pRet);
+}
+
+/*
+** Add the RETURNING clause to the parse currently underway.
+**
+** This routine creates a special TEMP trigger that will fire for each row
+** of the DML statement. That TEMP trigger contains a single SELECT
+** statement with a result set that is the argument of the RETURNING clause.
+** The trigger has the Trigger.bReturning flag and an opcode of
+** TK_RETURNING instead of TK_SELECT, so that the trigger code generator
+** knows to handle it specially. The TEMP trigger is automatically
+** removed at the end of the parse.
+**
+** When this routine is called, we do not yet know if the RETURNING clause
+** is attached to a DELETE, INSERT, or UPDATE, so construct it as a
+** RETURNING trigger instead. It will then be converted into the appropriate
+** type on the first call to sqlcipher_sqlite3TriggersExist().
+*/
+SQLITE_PRIVATE void sqlcipher_sqlite3AddReturning(Parse *pParse, ExprList *pList){
+ Returning *pRet;
+ Hash *pHash;
+ sqlcipher_sqlite3 *db = pParse->db;
+ if( pParse->pNewTrigger ){
+ sqlcipher_sqlite3ErrorMsg(pParse, "cannot use RETURNING in a trigger");
+ }else{
+ assert( pParse->bReturning==0 );
+ }
+ pParse->bReturning = 1;
+ pRet = sqlcipher_sqlite3DbMallocZero(db, sizeof(*pRet));
+ if( pRet==0 ){
+ sqlcipher_sqlite3ExprListDelete(db, pList);
+ return;
+ }
+ pParse->u1.pReturning = pRet;
+ pRet->pParse = pParse;
+ pRet->pReturnEL = pList;
+ sqlcipher_sqlite3ParserAddCleanup(pParse,
+ (void(*)(sqlcipher_sqlite3*,void*))sqlcipher_sqlite3DeleteReturning, pRet);
+ testcase( pParse->earlyCleanup );
+ if( db->mallocFailed ) return;
+ pRet->retTrig.zName = RETURNING_TRIGGER_NAME;
+ pRet->retTrig.op = TK_RETURNING;
+ pRet->retTrig.tr_tm = TRIGGER_AFTER;
+ pRet->retTrig.bReturning = 1;
+ pRet->retTrig.pSchema = db->aDb[1].pSchema;
+ pRet->retTrig.pTabSchema = db->aDb[1].pSchema;
+ pRet->retTrig.step_list = &pRet->retTStep;
+ pRet->retTStep.op = TK_RETURNING;
+ pRet->retTStep.pTrig = &pRet->retTrig;
+ pRet->retTStep.pExprList = pList;
+ pHash = &(db->aDb[1].pSchema->trigHash);
+ assert( sqlcipher_sqlite3HashFind(pHash, RETURNING_TRIGGER_NAME)==0 || pParse->nErr );
+ if( sqlcipher_sqlite3HashInsert(pHash, RETURNING_TRIGGER_NAME, &pRet->retTrig)
+ ==&pRet->retTrig ){
+ sqlcipher_sqlite3OomFault(db);
+ }
+}
/*
** Add a new column to the table currently being constructed.
@@ -116866,60 +121908,104 @@ SQLITE_PRIVATE void sqlcipher_sqlite3ColumnPropertiesFromName(Table *pTab, Colum
** first to get things going. Then this routine is called for each
** column.
*/
-SQLITE_PRIVATE void sqlcipher_sqlite3AddColumn(Parse *pParse, Token *pName, Token *pType){
+SQLITE_PRIVATE void sqlcipher_sqlite3AddColumn(Parse *pParse, Token sName, Token sType){
Table *p;
int i;
char *z;
char *zType;
Column *pCol;
sqlcipher_sqlite3 *db = pParse->db;
+ u8 hName;
+ Column *aNew;
+ u8 eType = COLTYPE_CUSTOM;
+ u8 szEst = 1;
+ char affinity = SQLITE_AFF_BLOB;
+
if( (p = pParse->pNewTable)==0 ) return;
if( p->nCol+1>db->aLimit[SQLITE_LIMIT_COLUMN] ){
sqlcipher_sqlite3ErrorMsg(pParse, "too many columns on %s", p->zName);
return;
}
- z = sqlcipher_sqlite3DbMallocRaw(db, pName->n + pType->n + 2);
+ if( !IN_RENAME_OBJECT ) sqlcipher_sqlite3DequoteToken(&sName);
+
+ /* Because keywords GENERATE ALWAYS can be converted into indentifiers
+ ** by the parser, we can sometimes end up with a typename that ends
+ ** with "generated always". Check for this case and omit the surplus
+ ** text. */
+ if( sType.n>=16
+ && sqlcipher_sqlite3_strnicmp(sType.z+(sType.n-6),"always",6)==0
+ ){
+ sType.n -= 6;
+ while( ALWAYS(sType.n>0) && sqlcipher_sqlite3Isspace(sType.z[sType.n-1]) ) sType.n--;
+ if( sType.n>=9
+ && sqlcipher_sqlite3_strnicmp(sType.z+(sType.n-9),"generated",9)==0
+ ){
+ sType.n -= 9;
+ while( sType.n>0 && sqlcipher_sqlite3Isspace(sType.z[sType.n-1]) ) sType.n--;
+ }
+ }
+
+ /* Check for standard typenames. For standard typenames we will
+ ** set the Column.eType field rather than storing the typename after
+ ** the column name, in order to save space. */
+ if( sType.n>=3 ){
+ sqlcipher_sqlite3DequoteToken(&sType);
+ for(i=0; i<SQLITE_N_STDTYPE; i++){
+ if( sType.n==sqlcipher_sqlite3StdTypeLen[i]
+ && sqlcipher_sqlite3_strnicmp(sType.z, sqlcipher_sqlite3StdType[i], sType.n)==0
+ ){
+ sType.n = 0;
+ eType = i+1;
+ affinity = sqlcipher_sqlite3StdTypeAffinity[i];
+ if( affinity<=SQLITE_AFF_TEXT ) szEst = 5;
+ break;
+ }
+ }
+ }
+
+ z = sqlcipher_sqlite3DbMallocRaw(db, (i64)sName.n + 1 + (i64)sType.n + (sType.n>0) );
if( z==0 ) return;
- if( IN_RENAME_OBJECT ) sqlcipher_sqlite3RenameTokenMap(pParse, (void*)z, pName);
- memcpy(z, pName->z, pName->n);
- z[pName->n] = 0;
+ if( IN_RENAME_OBJECT ) sqlcipher_sqlite3RenameTokenMap(pParse, (void*)z, &sName);
+ memcpy(z, sName.z, sName.n);
+ z[sName.n] = 0;
sqlcipher_sqlite3Dequote(z);
+ hName = sqlcipher_sqlite3StrIHash(z);
for(i=0; i<p->nCol; i++){
- if( sqlcipher_sqlite3_stricmp(z, p->aCol[i].zName)==0 ){
+ if( p->aCol[i].hName==hName && sqlcipher_sqlite3StrICmp(z, p->aCol[i].zCnName)==0 ){
sqlcipher_sqlite3ErrorMsg(pParse, "duplicate column name: %s", z);
sqlcipher_sqlite3DbFree(db, z);
return;
}
}
- if( (p->nCol & 0x7)==0 ){
- Column *aNew;
- aNew = sqlcipher_sqlite3DbRealloc(db,p->aCol,(p->nCol+8)*sizeof(p->aCol[0]));
- if( aNew==0 ){
- sqlcipher_sqlite3DbFree(db, z);
- return;
- }
- p->aCol = aNew;
+ aNew = sqlcipher_sqlite3DbRealloc(db,p->aCol,((i64)p->nCol+1)*sizeof(p->aCol[0]));
+ if( aNew==0 ){
+ sqlcipher_sqlite3DbFree(db, z);
+ return;
}
+ p->aCol = aNew;
pCol = &p->aCol[p->nCol];
memset(pCol, 0, sizeof(p->aCol[0]));
- pCol->zName = z;
- pCol->hName = sqlcipher_sqlite3StrIHash(z);
+ pCol->zCnName = z;
+ pCol->hName = hName;
sqlcipher_sqlite3ColumnPropertiesFromName(p, pCol);
- if( pType->n==0 ){
+ if( sType.n==0 ){
/* If there is no type specified, columns have the default affinity
** 'BLOB' with a default size of 4 bytes. */
- pCol->affinity = SQLITE_AFF_BLOB;
- pCol->szEst = 1;
+ pCol->affinity = affinity;
+ pCol->eCType = eType;
+ pCol->szEst = szEst;
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
- if( 4>=sqlcipher_sqlite3GlobalConfig.szSorterRef ){
- pCol->colFlags |= COLFLAG_SORTERREF;
+ if( affinity==SQLITE_AFF_BLOB ){
+ if( 4>=sqlcipher_sqlite3GlobalConfig.szSorterRef ){
+ pCol->colFlags |= COLFLAG_SORTERREF;
+ }
}
#endif
}else{
zType = z + sqlcipher_sqlite3Strlen30(z) + 1;
- memcpy(zType, pType->z, pType->n);
- zType[pType->n] = 0;
+ memcpy(zType, sType.z, sType.n);
+ zType[sType.n] = 0;
sqlcipher_sqlite3Dequote(zType);
pCol->affinity = sqlcipher_sqlite3AffinityType(zType, pCol);
pCol->colFlags |= COLFLAG_HASTYPE;
@@ -117074,7 +122160,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3AddDefaultValue(
pCol = &(p->aCol[p->nCol-1]);
if( !sqlcipher_sqlite3ExprIsConstantOrFunction(pExpr, isInit) ){
sqlcipher_sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant",
- pCol->zName);
+ pCol->zCnName);
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
}else if( pCol->colFlags & COLFLAG_GENERATED ){
testcase( pCol->colFlags & COLFLAG_VIRTUAL );
@@ -117085,15 +122171,15 @@ SQLITE_PRIVATE void sqlcipher_sqlite3AddDefaultValue(
/* A copy of pExpr is used instead of the original, as pExpr contains
** tokens that point to volatile memory.
*/
- Expr x;
- sqlcipher_sqlite3ExprDelete(db, pCol->pDflt);
+ Expr x, *pDfltExpr;
memset(&x, 0, sizeof(x));
x.op = TK_SPAN;
x.u.zToken = sqlcipher_sqlite3DbSpanDup(db, zStart, zEnd);
x.pLeft = pExpr;
x.flags = EP_Skip;
- pCol->pDflt = sqlcipher_sqlite3ExprDup(db, &x, EXPRDUP_REDUCE);
+ pDfltExpr = sqlcipher_sqlite3ExprDup(db, &x, EXPRDUP_REDUCE);
sqlcipher_sqlite3DbFree(db, x.u.zToken);
+ sqlcipher_sqlite3ColumnSetExpr(pParse, p, pCol, pDfltExpr);
}
}
if( IN_RENAME_OBJECT ){
@@ -117189,9 +122275,11 @@ SQLITE_PRIVATE void sqlcipher_sqlite3AddPrimaryKey(
assert( pCExpr!=0 );
sqlcipher_sqlite3StringToId(pCExpr);
if( pCExpr->op==TK_ID ){
- const char *zCName = pCExpr->u.zToken;
+ const char *zCName;
+ assert( !ExprHasProperty(pCExpr, EP_IntValue) );
+ zCName = pCExpr->u.zToken;
for(iCol=0; iCol<pTab->nCol; iCol++){
- if( sqlcipher_sqlite3StrICmp(zCName, pTab->aCol[iCol].zName)==0 ){
+ if( sqlcipher_sqlite3StrICmp(zCName, pTab->aCol[iCol].zCnName)==0 ){
pCol = &pTab->aCol[iCol];
makeColumnPartOfPrimaryKey(pParse, pCol);
break;
@@ -117202,7 +122290,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3AddPrimaryKey(
}
if( nTerm==1
&& pCol
- && sqlcipher_sqlite3StrICmp(sqlcipher_sqlite3ColumnType(pCol,""), "INTEGER")==0
+ && pCol->eCType==COLTYPE_INTEGER
&& sortOrder!=SQLITE_SO_DESC
){
if( IN_RENAME_OBJECT && pList ){
@@ -117213,7 +122301,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3AddPrimaryKey(
pTab->keyConf = (u8)onError;
assert( autoInc==0 || autoInc==1 );
pTab->tabFlags |= autoInc*TF_Autoincrement;
- if( pList ) pParse->iPkSortOrder = pList->a[0].sortFlags;
+ if( pList ) pParse->iPkSortOrder = pList->a[0].fg.sortFlags;
(void)sqlcipher_sqlite3HasExplicitNulls(pParse, pList);
}else if( autoInc ){
#ifndef SQLITE_OMIT_AUTOINCREMENT
@@ -117282,8 +122370,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3AddCollateType(Parse *pParse, Token *pToken
if( sqlcipher_sqlite3LocateCollSeq(pParse, zColl) ){
Index *pIdx;
- sqlcipher_sqlite3DbFree(db, p->aCol[i].zColl);
- p->aCol[i].zColl = zColl;
+ sqlcipher_sqlite3ColumnSetColl(db, &p->aCol[i], zColl);
/* If the column is declared as "<name> PRIMARY KEY COLLATE <type>",
** then an index may have been created on this column before the
@@ -117292,12 +122379,11 @@ SQLITE_PRIVATE void sqlcipher_sqlite3AddCollateType(Parse *pParse, Token *pToken
for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){
assert( pIdx->nKeyCol==1 );
if( pIdx->aiColumn[0]==i ){
- pIdx->azColl[0] = p->aCol[i].zColl;
+ pIdx->azColl[0] = sqlcipher_sqlite3ColumnColl(&p->aCol[i]);
}
}
- }else{
- sqlcipher_sqlite3DbFree(db, zColl);
}
+ sqlcipher_sqlite3DbFree(db, zColl);
}
/* Change the most recently parsed column to be a GENERATED ALWAYS AS
@@ -117317,7 +122403,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3AddGenerated(Parse *pParse, Expr *pExpr, To
sqlcipher_sqlite3ErrorMsg(pParse, "virtual tables cannot use computed columns");
goto generated_done;
}
- if( pCol->pDflt ) goto generated_error;
+ if( pCol->iDflt>0 ) goto generated_error;
if( pType ){
if( pType->n==7 && sqlcipher_sqlite3StrNICmp("virtual",pType->z,7)==0 ){
/* no-op */
@@ -117335,13 +122421,13 @@ SQLITE_PRIVATE void sqlcipher_sqlite3AddGenerated(Parse *pParse, Expr *pExpr, To
if( pCol->colFlags & COLFLAG_PRIMKEY ){
makeColumnPartOfPrimaryKey(pParse, pCol); /* For the error message */
}
- pCol->pDflt = pExpr;
+ sqlcipher_sqlite3ColumnSetExpr(pParse, pTab, pCol, pExpr);
pExpr = 0;
goto generated_done;
generated_error:
sqlcipher_sqlite3ErrorMsg(pParse, "error in generated column \"%s\"",
- pCol->zName);
+ pCol->zCnName);
generated_done:
sqlcipher_sqlite3ExprDelete(pParse->db, pExpr);
#else
@@ -117443,7 +122529,7 @@ static char *createTableStmt(sqlcipher_sqlite3 *db, Table *p){
Column *pCol;
n = 0;
for(pCol = p->aCol, i=0; i<p->nCol; i++, pCol++){
- n += identLength(pCol->zName) + 5;
+ n += identLength(pCol->zCnName) + 5;
}
n += identLength(p->zName);
if( n<50 ){
@@ -117479,7 +122565,7 @@ static char *createTableStmt(sqlcipher_sqlite3 *db, Table *p){
sqlcipher_sqlite3_snprintf(n-k, &zStmt[k], zSep);
k += sqlcipher_sqlite3Strlen30(&zStmt[k]);
zSep = zSep2;
- identPut(zStmt, &k, pCol->zName);
+ identPut(zStmt, &k, pCol->zCnName);
assert( pCol->affinity-SQLITE_AFF_BLOB >= 0 );
assert( pCol->affinity-SQLITE_AFF_BLOB < ArraySize(azType) );
testcase( pCol->affinity==SQLITE_AFF_BLOB );
@@ -117563,7 +122649,6 @@ static void estimateIndexWidth(Index *pIdx){
*/
static int hasColumn(const i16 *aiCol, int nCol, int x){
while( nCol-- > 0 ){
- assert( aiCol[0]>=0 );
if( x==*(aiCol++) ){
return 1;
}
@@ -117676,7 +122761,9 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
*/
if( !db->init.imposterTable ){
for(i=0; i<pTab->nCol; i++){
- if( (pTab->aCol[i].colFlags & COLFLAG_PRIMKEY)!=0 ){
+ if( (pTab->aCol[i].colFlags & COLFLAG_PRIMKEY)!=0
+ && (pTab->aCol[i].notNull==OE_None)
+ ){
pTab->aCol[i].notNull = OE_Abort;
}
}
@@ -117686,9 +122773,10 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
/* Convert the P3 operand of the OP_CreateBtree opcode from BTREE_INTKEY
** into BTREE_BLOBKEY.
*/
- if( pParse->addrCrTab ){
+ assert( !pParse->bReturning );
+ if( pParse->u1.addrCrTab ){
assert( v );
- sqlcipher_sqlite3VdbeChangeP3(v, pParse->addrCrTab, BTREE_BLOBKEY);
+ sqlcipher_sqlite3VdbeChangeP3(v, pParse->u1.addrCrTab, BTREE_BLOBKEY);
}
/* Locate the PRIMARY KEY index. Or, if this table was originally
@@ -117697,19 +122785,26 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
if( pTab->iPKey>=0 ){
ExprList *pList;
Token ipkToken;
- sqlcipher_sqlite3TokenInit(&ipkToken, pTab->aCol[pTab->iPKey].zName);
+ sqlcipher_sqlite3TokenInit(&ipkToken, pTab->aCol[pTab->iPKey].zCnName);
pList = sqlcipher_sqlite3ExprListAppend(pParse, 0,
sqlcipher_sqlite3ExprAlloc(db, TK_ID, &ipkToken, 0));
- if( pList==0 ) return;
+ if( pList==0 ){
+ pTab->tabFlags &= ~TF_WithoutRowid;
+ return;
+ }
if( IN_RENAME_OBJECT ){
sqlcipher_sqlite3RenameTokenRemap(pParse, pList->a[0].pExpr, &pTab->iPKey);
}
- pList->a[0].sortFlags = pParse->iPkSortOrder;
+ pList->a[0].fg.sortFlags = pParse->iPkSortOrder;
assert( pParse->pNewTable==pTab );
pTab->iPKey = -1;
sqlcipher_sqlite3CreateIndex(pParse, 0, 0, 0, pList, pTab->keyConf, 0, 0, 0, 0,
SQLITE_IDXTYPE_PRIMARYKEY);
- if( db->mallocFailed || pParse->nErr ) return;
+ if( pParse->nErr ){
+ pTab->tabFlags &= ~TF_WithoutRowid;
+ return;
+ }
+ assert( db->mallocFailed==0 );
pPk = sqlcipher_sqlite3PrimaryKeyIndex(pTab);
assert( pPk->nKeyCol==1 );
}else{
@@ -117821,7 +122916,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3IsShadowTableOf(sqlcipher_sqlite3 *db, Table
nName = sqlcipher_sqlite3Strlen30(pTab->zName);
if( sqlcipher_sqlite3_strnicmp(zName, pTab->zName, nName)!=0 ) return 0;
if( zName[nName]!='_' ) return 0;
- pMod = (Module*)sqlcipher_sqlite3HashFind(&db->aModule, pTab->azModuleArg[0]);
+ pMod = (Module*)sqlcipher_sqlite3HashFind(&db->aModule, pTab->u.vtab.azArg[0]);
if( pMod==0 ) return 0;
if( pMod->pModule->iVersion<3 ) return 0;
if( pMod->pModule->xShadowName==0 ) return 0;
@@ -117831,6 +122926,41 @@ SQLITE_PRIVATE int sqlcipher_sqlite3IsShadowTableOf(sqlcipher_sqlite3 *db, Table
#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
+** Table pTab is a virtual table. If it the virtual table implementation
+** exists and has an xShadowName method, then loop over all other ordinary
+** tables within the same schema looking for shadow tables of pTab, and mark
+** any shadow tables seen using the TF_Shadow flag.
+*/
+SQLITE_PRIVATE void sqlcipher_sqlite3MarkAllShadowTablesOf(sqlcipher_sqlite3 *db, Table *pTab){
+ int nName; /* Length of pTab->zName */
+ Module *pMod; /* Module for the virtual table */
+ HashElem *k; /* For looping through the symbol table */
+
+ assert( IsVirtual(pTab) );
+ pMod = (Module*)sqlcipher_sqlite3HashFind(&db->aModule, pTab->u.vtab.azArg[0]);
+ if( pMod==0 ) return;
+ if( NEVER(pMod->pModule==0) ) return;
+ if( pMod->pModule->iVersion<3 ) return;
+ if( pMod->pModule->xShadowName==0 ) return;
+ assert( pTab->zName!=0 );
+ nName = sqlcipher_sqlite3Strlen30(pTab->zName);
+ for(k=sqliteHashFirst(&pTab->pSchema->tblHash); k; k=sqliteHashNext(k)){
+ Table *pOther = sqliteHashData(k);
+ assert( pOther->zName!=0 );
+ if( !IsOrdinaryTable(pOther) ) continue;
+ if( pOther->tabFlags & TF_Shadow ) continue;
+ if( sqlcipher_sqlite3StrNICmp(pOther->zName, pTab->zName, nName)==0
+ && pOther->zName[nName]=='_'
+ && pMod->pModule->xShadowName(pOther->zName+nName+1)
+ ){
+ pOther->tabFlags |= TF_Shadow;
+ }
+ }
+}
+#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/*
** Return true if zName is a shadow table name in the current database
** connection.
**
@@ -117902,7 +123032,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3EndTable(
Parse *pParse, /* Parse context */
Token *pCons, /* The ',' token after the last column defn. */
Token *pEnd, /* The ')' before options in the CREATE TABLE */
- u8 tabOpts, /* Extra table options. Usually 0. */
+ u32 tabOpts, /* Extra table options. Usually 0. */
Select *pSelect /* Select from a "CREATE ... AS SELECT" */
){
Table *p; /* The new table */
@@ -117913,7 +123043,6 @@ SQLITE_PRIVATE void sqlcipher_sqlite3EndTable(
if( pEnd==0 && pSelect==0 ){
return;
}
- assert( !db->mallocFailed );
p = pParse->pNewTable;
if( p==0 ) return;
@@ -117931,7 +123060,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3EndTable(
** table itself. So mark it read-only.
*/
if( db->init.busy ){
- if( pSelect ){
+ if( pSelect || (!IsOrdinaryTable(p) && db->init.newTnum) ){
sqlcipher_sqlite3ErrorMsg(pParse, "");
return;
}
@@ -117939,6 +123068,44 @@ SQLITE_PRIVATE void sqlcipher_sqlite3EndTable(
if( p->tnum==1 ) p->tabFlags |= TF_Readonly;
}
+ /* Special processing for tables that include the STRICT keyword:
+ **
+ ** * Do not allow custom column datatypes. Every column must have
+ ** a datatype that is one of INT, INTEGER, REAL, TEXT, or BLOB.
+ **
+ ** * If a PRIMARY KEY is defined, other than the INTEGER PRIMARY KEY,
+ ** then all columns of the PRIMARY KEY must have a NOT NULL
+ ** constraint.
+ */
+ if( tabOpts & TF_Strict ){
+ int ii;
+ p->tabFlags |= TF_Strict;
+ for(ii=0; ii<p->nCol; ii++){
+ Column *pCol = &p->aCol[ii];
+ if( pCol->eCType==COLTYPE_CUSTOM ){
+ if( pCol->colFlags & COLFLAG_HASTYPE ){
+ sqlcipher_sqlite3ErrorMsg(pParse,
+ "unknown datatype for %s.%s: \"%s\"",
+ p->zName, pCol->zCnName, sqlcipher_sqlite3ColumnType(pCol, "")
+ );
+ }else{
+ sqlcipher_sqlite3ErrorMsg(pParse, "missing datatype for %s.%s",
+ p->zName, pCol->zCnName);
+ }
+ return;
+ }else if( pCol->eCType==COLTYPE_ANY ){
+ pCol->affinity = SQLITE_AFF_BLOB;
+ }
+ if( (pCol->colFlags & COLFLAG_PRIMKEY)!=0
+ && p->iPKey!=ii
+ && pCol->notNull == OE_None
+ ){
+ pCol->notNull = OE_Abort;
+ p->tabFlags |= TF_HasNotNull;
+ }
+ }
+ }
+
assert( (p->tabFlags & TF_HasPrimaryKey)==0
|| p->iPKey>=0 || sqlcipher_sqlite3PrimaryKeyIndex(p)!=0 );
assert( (p->tabFlags & TF_HasPrimaryKey)!=0
@@ -117983,7 +123150,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3EndTable(
for(ii=0; ii<p->nCol; ii++){
u32 colFlags = p->aCol[ii].colFlags;
if( (colFlags & COLFLAG_GENERATED)!=0 ){
- Expr *pX = p->aCol[ii].pDflt;
+ Expr *pX = sqlcipher_sqlite3ColumnExpr(p, &p->aCol[ii]);
testcase( colFlags & COLFLAG_VIRTUAL );
testcase( colFlags & COLFLAG_STORED );
if( sqlcipher_sqlite3ResolveSelfReference(pParse, p, NC_GenCol, pX, 0) ){
@@ -117993,8 +123160,8 @@ SQLITE_PRIVATE void sqlcipher_sqlite3EndTable(
** tree that have been allocated from lookaside memory, which is
** illegal in a schema and will lead to errors or heap corruption
** when the database connection closes. */
- sqlcipher_sqlite3ExprDelete(db, pX);
- p->aCol[ii].pDflt = sqlcipher_sqlite3ExprAlloc(db, TK_NULL, 0, 0);
+ sqlcipher_sqlite3ColumnSetExpr(pParse, p, &p->aCol[ii],
+ sqlcipher_sqlite3ExprAlloc(db, TK_NULL, 0, 0));
}
}else{
nNG++;
@@ -118034,7 +123201,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3EndTable(
/*
** Initialize zType for the new view or table.
*/
- if( p->pSelect==0 ){
+ if( IsOrdinaryTable(p) ){
/* A regular table */
zType = "table";
zType2 = "TABLE";
@@ -118068,6 +123235,11 @@ SQLITE_PRIVATE void sqlcipher_sqlite3EndTable(
int addrInsLoop; /* Top of the loop for inserting rows */
Table *pSelTab; /* A table that describes the SELECT results */
+ if( IN_SPECIAL_PARSE ){
+ pParse->rc = SQLITE_ERROR;
+ pParse->nErr++;
+ return;
+ }
regYield = ++pParse->nMem;
regRec = ++pParse->nMem;
regRowid = ++pParse->nMem;
@@ -118120,7 +123292,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3EndTable(
** the information we've collected.
*/
sqlcipher_sqlite3NestedParse(pParse,
- "UPDATE %Q." DFLT_SCHEMA_TABLE
+ "UPDATE %Q." LEGACY_SCHEMA_TABLE
" SET type='%s', name=%Q, tbl_name=%Q, rootpage=#%d, sql=%Q"
" WHERE rowid=#%d",
db->aDb[iDb].zDbSName,
@@ -118138,7 +123310,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3EndTable(
/* Check to see if we need to create an sqlite_sequence table for
** keeping track of autoincrement keys.
*/
- if( (p->tabFlags & TF_Autoincrement)!=0 ){
+ if( (p->tabFlags & TF_Autoincrement)!=0 && !IN_SPECIAL_PARSE ){
Db *pDb = &db->aDb[iDb];
assert( sqlcipher_sqlite3SchemaMutexHeld(db, iDb, 0) );
if( pDb->pSchema->pSeqTab==0 ){
@@ -118152,7 +123324,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3EndTable(
/* Reparse everything to update our internal data structures */
sqlcipher_sqlite3VdbeAddParseSchemaOp(v, iDb,
- sqlcipher_sqlite3MPrintf(db, "tbl_name='%q' AND type!='trigger'", p->zName));
+ sqlcipher_sqlite3MPrintf(db, "tbl_name='%q' AND type!='trigger'", p->zName),0);
}
/* Add the table to the in-memory representation of the database.
@@ -118161,6 +123333,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3EndTable(
Table *pOld;
Schema *pSchema = p->pSchema;
assert( sqlcipher_sqlite3SchemaMutexHeld(db, iDb, 0) );
+ assert( HasRowid(p) || p->iPKey<0 );
pOld = sqlcipher_sqlite3HashInsert(&pSchema->tblHash, p->zName, p);
if( pOld ){
assert( p==pOld ); /* Malloc must have failed inside HashInsert() */
@@ -118170,19 +123343,27 @@ SQLITE_PRIVATE void sqlcipher_sqlite3EndTable(
pParse->pNewTable = 0;
db->mDbFlags |= DBFLAG_SchemaChange;
-#ifndef SQLITE_OMIT_ALTERTABLE
- if( !p->pSelect ){
- const char *zName = (const char *)pParse->sNameToken.z;
- int nName;
- assert( !pSelect && pCons && pEnd );
- if( pCons->z==0 ){
- pCons = pEnd;
- }
- nName = (int)((const char *)pCons->z - zName);
- p->addColOffset = 13 + sqlcipher_sqlite3Utf8CharLen(zName, nName);
+ /* If this is the magic sqlite_sequence table used by autoincrement,
+ ** then record a pointer to this table in the main database structure
+ ** so that INSERT can find the table easily. */
+ assert( !pParse->nested );
+#ifndef SQLITE_OMIT_AUTOINCREMENT
+ if( strcmp(p->zName, "sqlite_sequence")==0 ){
+ assert( sqlcipher_sqlite3SchemaMutexHeld(db, iDb, 0) );
+ p->pSchema->pSeqTab = p;
}
#endif
}
+
+#ifndef SQLITE_OMIT_ALTERTABLE
+ if( !pSelect && IsOrdinaryTable(p) ){
+ assert( pCons && pEnd );
+ if( pCons->z==0 ){
+ pCons = pEnd;
+ }
+ p->u.tab.addColOffset = 13 + (int)(pCons->z - pParse->sNameToken.z);
+ }
+#endif
}
#ifndef SQLITE_OMIT_VIEW
@@ -118215,6 +123396,16 @@ SQLITE_PRIVATE void sqlcipher_sqlite3CreateView(
sqlcipher_sqlite3StartTable(pParse, pName1, pName2, isTemp, 1, 0, noErr);
p = pParse->pNewTable;
if( p==0 || pParse->nErr ) goto create_view_fail;
+
+ /* Legacy versions of SQLite allowed the use of the magic "rowid" column
+ ** on a view, even though views do not have rowids. The following flag
+ ** setting fixes this problem. But the fix can be disabled by compiling
+ ** with -DSQLITE_ALLOW_ROWID_IN_VIEW in case there are legacy apps that
+ ** depend upon the old buggy behavior. */
+#ifndef SQLITE_ALLOW_ROWID_IN_VIEW
+ p->tabFlags |= TF_NoVisibleRowid;
+#endif
+
sqlcipher_sqlite3TwoPartName(pParse, pName1, pName2, &pName);
iDb = sqlcipher_sqlite3SchemaToIndex(db, p->pSchema);
sqlcipher_sqlite3FixInit(&sFix, pParse, iDb, "view", pName);
@@ -118227,12 +123418,13 @@ SQLITE_PRIVATE void sqlcipher_sqlite3CreateView(
*/
pSelect->selFlags |= SF_View;
if( IN_RENAME_OBJECT ){
- p->pSelect = pSelect;
+ p->u.view.pSelect = pSelect;
pSelect = 0;
}else{
- p->pSelect = sqlcipher_sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);
+ p->u.view.pSelect = sqlcipher_sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);
}
p->pCheck = sqlcipher_sqlite3ExprListDup(db, pCNames, EXPRDUP_REDUCE);
+ p->eTabType = TABTYP_VIEW;
if( db->mallocFailed ) goto create_view_fail;
/* Locate the end of the CREATE VIEW statement. Make sEnd point to
@@ -118274,7 +123466,6 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ViewGetColumnNames(Parse *pParse, Table *pTa
Table *pSelTab; /* A fake table from which we get the result set */
Select *pSel; /* Copy of the SELECT that implements the view */
int nErr = 0; /* Number of errors encountered */
- int n; /* Temporarily holds the number of cursors assigned */
sqlcipher_sqlite3 *db = pParse->db; /* Database connection for malloc errors */
#ifndef SQLITE_OMIT_VIRTUALTABLE
int rc;
@@ -118286,13 +123477,12 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ViewGetColumnNames(Parse *pParse, Table *pTa
assert( pTable );
#ifndef SQLITE_OMIT_VIRTUALTABLE
- db->nSchemaLock++;
- rc = sqlcipher_sqlite3VtabCallConnect(pParse, pTable);
- db->nSchemaLock--;
- if( rc ){
- return 1;
+ if( IsVirtual(pTable) ){
+ db->nSchemaLock++;
+ rc = sqlcipher_sqlite3VtabCallConnect(pParse, pTable);
+ db->nSchemaLock--;
+ return rc;
}
- if( IsVirtual(pTable) ) return 0;
#endif
#ifndef SQLITE_OMIT_VIEW
@@ -118329,12 +123519,13 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ViewGetColumnNames(Parse *pParse, Table *pTa
** to be permanent. So the computation is done on a copy of the SELECT
** statement that defines the view.
*/
- assert( pTable->pSelect );
- pSel = sqlcipher_sqlite3SelectDup(db, pTable->pSelect, 0);
+ assert( IsView(pTable) );
+ pSel = sqlcipher_sqlite3SelectDup(db, pTable->u.view.pSelect, 0);
if( pSel ){
u8 eParseMode = pParse->eParseMode;
+ int nTab = pParse->nTab;
+ int nSelect = pParse->nSelect;
pParse->eParseMode = PARSE_MODE_NORMAL;
- n = pParse->nTab;
sqlcipher_sqlite3SrcListAssignCursors(pParse, pSel->pSrc);
pTable->nCol = -1;
DisableLookaside;
@@ -118346,7 +123537,8 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ViewGetColumnNames(Parse *pParse, Table *pTa
#else
pSelTab = sqlcipher_sqlite3ResultSetOfSelect(pParse, pSel, SQLITE_AFF_NONE);
#endif
- pParse->nTab = n;
+ pParse->nTab = nTab;
+ pParse->nSelect = nSelect;
if( pSelTab==0 ){
pTable->nCol = 0;
nErr++;
@@ -118359,10 +123551,10 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ViewGetColumnNames(Parse *pParse, Table *pTa
*/
sqlcipher_sqlite3ColumnsFromExprList(pParse, pTable->pCheck,
&pTable->nCol, &pTable->aCol);
- if( db->mallocFailed==0
- && pParse->nErr==0
+ if( pParse->nErr==0
&& pTable->nCol==pSel->pEList->nExpr
){
+ assert( db->mallocFailed==0 );
sqlcipher_sqlite3SelectAddColumnTypeAndCollation(pParse, pTable, pSel,
SQLITE_AFF_NONE);
}
@@ -118373,6 +123565,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ViewGetColumnNames(Parse *pParse, Table *pTa
assert( pTable->aCol==0 );
pTable->nCol = pSelTab->nCol;
pTable->aCol = pSelTab->aCol;
+ pTable->tabFlags |= (pSelTab->tabFlags & COLFLAG_NOINSERT);
pSelTab->nCol = 0;
pSelTab->aCol = 0;
assert( sqlcipher_sqlite3SchemaMutexHeld(db, 0, pTable->pSchema) );
@@ -118388,8 +123581,6 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ViewGetColumnNames(Parse *pParse, Table *pTa
pTable->pSchema->schemaFlags |= DB_UnresetViews;
if( db->mallocFailed ){
sqlcipher_sqlite3DeleteColumnNames(db, pTable);
- pTable->aCol = 0;
- pTable->nCol = 0;
}
#endif /* SQLITE_OMIT_VIEW */
return nErr;
@@ -118406,10 +123597,8 @@ static void sqliteViewResetAll(sqlcipher_sqlite3 *db, int idx){
if( !DbHasProperty(db, idx, DB_UnresetViews) ) return;
for(i=sqliteHashFirst(&db->aDb[idx].pSchema->tblHash); i;i=sqliteHashNext(i)){
Table *pTab = sqliteHashData(i);
- if( pTab->pSelect ){
+ if( IsView(pTab) ){
sqlcipher_sqlite3DeleteColumnNames(db, pTab);
- pTab->aCol = 0;
- pTab->nCol = 0;
}
}
DbClearProperty(db, idx, DB_UnresetViews);
@@ -118483,7 +123672,7 @@ static void destroyRootPage(Parse *pParse, int iTable, int iDb){
** token for additional information.
*/
sqlcipher_sqlite3NestedParse(pParse,
- "UPDATE %Q." DFLT_SCHEMA_TABLE
+ "UPDATE %Q." LEGACY_SCHEMA_TABLE
" SET rootpage=%d WHERE #%d AND rootpage=#%d",
pParse->db->aDb[iDb].zDbSName, iTable, r1, r1);
#endif
@@ -118618,7 +123807,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3CodeDropTable(Parse *pParse, Table *pTab, i
** database.
*/
sqlcipher_sqlite3NestedParse(pParse,
- "DELETE FROM %Q." DFLT_SCHEMA_TABLE
+ "DELETE FROM %Q." LEGACY_SCHEMA_TABLE
" WHERE tbl_name=%Q and type!='trigger'",
pDb->zDbSName, pTab->zName);
if( !isView && !IsVirtual(pTab) ){
@@ -118646,6 +123835,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ReadOnlyShadowTables(sqlcipher_sqlite3 *db){
if( (db->flags & SQLITE_Defensive)!=0
&& db->pVtabCtx==0
&& db->nVdbeExec==0
+ && !sqlcipher_sqlite3VtabInSync(db)
){
return 1;
}
@@ -118665,6 +123855,9 @@ static int tableMayNotBeDropped(sqlcipher_sqlite3 *db, Table *pTab){
if( (pTab->tabFlags & TF_Shadow)!=0 && sqlcipher_sqlite3ReadOnlyShadowTables(db) ){
return 1;
}
+ if( pTab->tabFlags & TF_Eponymous ){
+ return 1;
+ }
return 0;
}
@@ -118690,7 +123883,10 @@ SQLITE_PRIVATE void sqlcipher_sqlite3DropTable(Parse *pParse, SrcList *pName, in
if( noErr ) db->suppressErr--;
if( pTab==0 ){
- if( noErr ) sqlcipher_sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase);
+ if( noErr ){
+ sqlcipher_sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase);
+ sqlcipher_sqlite3ForceNotReadOnly(pParse);
+ }
goto exit_drop_table;
}
iDb = sqlcipher_sqlite3SchemaToIndex(db, pTab->pSchema);
@@ -118746,11 +123942,11 @@ SQLITE_PRIVATE void sqlcipher_sqlite3DropTable(Parse *pParse, SrcList *pName, in
/* Ensure DROP TABLE is not used on a view, and DROP VIEW is not used
** on a table.
*/
- if( isView && pTab->pSelect==0 ){
+ if( isView && !IsView(pTab) ){
sqlcipher_sqlite3ErrorMsg(pParse, "use DROP TABLE to delete table %s", pTab->zName);
goto exit_drop_table;
}
- if( !isView && pTab->pSelect ){
+ if( !isView && IsView(pTab) ){
sqlcipher_sqlite3ErrorMsg(pParse, "use DROP VIEW to delete view %s", pTab->zName);
goto exit_drop_table;
}
@@ -118801,7 +123997,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3CreateForeignKey(
FKey *pFKey = 0;
FKey *pNextTo;
Table *p = pParse->pNewTable;
- int nByte;
+ i64 nByte;
int i;
int nCol;
char *z;
@@ -118814,7 +124010,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3CreateForeignKey(
if( pToCol && pToCol->nExpr!=1 ){
sqlcipher_sqlite3ErrorMsg(pParse, "foreign key on %s"
" should reference only one column of table %T",
- p->aCol[iCol].zName, pTo);
+ p->aCol[iCol].zCnName, pTo);
goto fk_end;
}
nCol = 1;
@@ -118837,7 +124033,8 @@ SQLITE_PRIVATE void sqlcipher_sqlite3CreateForeignKey(
goto fk_end;
}
pFKey->pFrom = p;
- pFKey->pNextFrom = p->pFKey;
+ assert( IsOrdinaryTable(p) );
+ pFKey->pNextFrom = p->u.tab.pFKey;
z = (char*)&pFKey->aCol[nCol];
pFKey->zTo = z;
if( IN_RENAME_OBJECT ){
@@ -118854,7 +124051,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3CreateForeignKey(
for(i=0; i<nCol; i++){
int j;
for(j=0; j<p->nCol; j++){
- if( sqlcipher_sqlite3StrICmp(p->aCol[j].zName, pFromCol->a[i].zEName)==0 ){
+ if( sqlcipher_sqlite3StrICmp(p->aCol[j].zCnName, pFromCol->a[i].zEName)==0 ){
pFKey->aCol[i].iFrom = j;
break;
}
@@ -118902,7 +124099,8 @@ SQLITE_PRIVATE void sqlcipher_sqlite3CreateForeignKey(
/* Link the foreign key to the table as the last step.
*/
- p->pFKey = pFKey;
+ assert( IsOrdinaryTable(p) );
+ p->u.tab.pFKey = pFKey;
pFKey = 0;
fk_end:
@@ -118923,7 +124121,9 @@ SQLITE_PRIVATE void sqlcipher_sqlite3DeferForeignKey(Parse *pParse, int isDeferr
#ifndef SQLITE_OMIT_FOREIGN_KEY
Table *pTab;
FKey *pFKey;
- if( (pTab = pParse->pNewTable)==0 || (pFKey = pTab->pFKey)==0 ) return;
+ if( (pTab = pParse->pNewTable)==0 ) return;
+ if( NEVER(!IsOrdinaryTable(pTab)) ) return;
+ if( (pFKey = pTab->u.tab.pFKey)==0 ) return;
assert( isDeferred==0 || isDeferred==1 ); /* EV: R-30323-21917 */
pFKey->isDeferred = (u8)isDeferred;
#endif
@@ -118973,7 +124173,7 @@ static void sqlcipher_sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRo
tnum = pIndex->tnum;
}
pKey = sqlcipher_sqlite3KeyInfoOfIndex(pParse, pIndex);
- assert( pKey!=0 || db->mallocFailed || pParse->nErr );
+ assert( pKey!=0 || pParse->nErr );
/* Open the sorter cursor if we are to use one. */
iSorter = pParse->nTab++;
@@ -119083,8 +124283,8 @@ SQLITE_PRIVATE int sqlcipher_sqlite3HasExplicitNulls(Parse *pParse, ExprList *pL
if( pList ){
int i;
for(i=0; i<pList->nExpr; i++){
- if( pList->a[i].bNulls ){
- u8 sf = pList->a[i].sortFlags;
+ if( pList->a[i].fg.bNulls ){
+ u8 sf = pList->a[i].fg.sortFlags;
sqlcipher_sqlite3ErrorMsg(pParse, "unsupported use of NULLS %s",
(sf==0 || sf==3) ? "FIRST" : "LAST"
);
@@ -119137,9 +124337,11 @@ SQLITE_PRIVATE void sqlcipher_sqlite3CreateIndex(
char *zExtra = 0; /* Extra space after the Index object */
Index *pPk = 0; /* PRIMARY KEY index for WITHOUT ROWID tables */
- if( db->mallocFailed || pParse->nErr>0 ){
+ assert( db->pParse==pParse );
+ if( pParse->nErr ){
goto exit_create_index;
}
+ assert( db->mallocFailed==0 );
if( IN_DECLARE_VTAB && idxType!=SQLITE_IDXTYPE_PRIMARYKEY ){
goto exit_create_index;
}
@@ -119203,7 +124405,6 @@ SQLITE_PRIVATE void sqlcipher_sqlite3CreateIndex(
pDb = &db->aDb[iDb];
assert( pTab!=0 );
- assert( pParse->nErr==0 );
if( sqlcipher_sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0
&& db->init.busy==0
&& pTblName!=0
@@ -119215,7 +124416,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3CreateIndex(
goto exit_create_index;
}
#ifndef SQLITE_OMIT_VIEW
- if( pTab->pSelect ){
+ if( IsView(pTab) ){
sqlcipher_sqlite3ErrorMsg(pParse, "views may not be indexed");
goto exit_create_index;
}
@@ -119260,6 +124461,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3CreateIndex(
}else{
assert( !db->init.busy );
sqlcipher_sqlite3CodeVerifySchema(pParse, iDb);
+ sqlcipher_sqlite3ForceNotReadOnly(pParse);
}
goto exit_create_index;
}
@@ -119305,7 +124507,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3CreateIndex(
Token prevCol;
Column *pCol = &pTab->aCol[pTab->nCol-1];
pCol->colFlags |= COLFLAG_UNIQUE;
- sqlcipher_sqlite3TokenInit(&prevCol, pCol->zName);
+ sqlcipher_sqlite3TokenInit(&prevCol, pCol->zCnName);
pList = sqlcipher_sqlite3ExprListAppend(pParse, 0,
sqlcipher_sqlite3ExprAlloc(db, TK_ID, &prevCol, 0));
if( pList==0 ) goto exit_create_index;
@@ -119323,6 +124525,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3CreateIndex(
Expr *pExpr = pList->a[i].pExpr;
assert( pExpr!=0 );
if( pExpr->op==TK_COLLATE ){
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
nExtra += (1 + sqlcipher_sqlite3Strlen30(pExpr->u.zToken));
}
}
@@ -119418,6 +124621,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3CreateIndex(
zColl = 0;
if( pListItem->pExpr->op==TK_COLLATE ){
int nColl;
+ assert( !ExprHasProperty(pListItem->pExpr, EP_IntValue) );
zColl = pListItem->pExpr->u.zToken;
nColl = sqlcipher_sqlite3Strlen30(zColl) + 1;
assert( nExtra>=nColl );
@@ -119426,14 +124630,14 @@ SQLITE_PRIVATE void sqlcipher_sqlite3CreateIndex(
zExtra += nColl;
nExtra -= nColl;
}else if( j>=0 ){
- zColl = pTab->aCol[j].zColl;
+ zColl = sqlcipher_sqlite3ColumnColl(&pTab->aCol[j]);
}
if( !zColl ) zColl = sqlcipher_sqlite3StrBINARY;
if( !db->init.busy && !sqlcipher_sqlite3LocateCollSeq(pParse, zColl) ){
goto exit_create_index;
}
pIndex->azColl[i] = zColl;
- requestedSortOrder = pListItem->sortFlags & sortOrderMask;
+ requestedSortOrder = pListItem->fg.sortFlags & sortOrderMask;
pIndex->aSortOrder[i] = (u8)requestedSortOrder;
}
@@ -119624,13 +124828,13 @@ SQLITE_PRIVATE void sqlcipher_sqlite3CreateIndex(
/* Add an entry in sqlite_schema for this index
*/
sqlcipher_sqlite3NestedParse(pParse,
- "INSERT INTO %Q." DFLT_SCHEMA_TABLE " VALUES('index',%Q,%Q,#%d,%Q);",
- db->aDb[iDb].zDbSName,
- pIndex->zName,
- pTab->zName,
- iMem,
- zStmt
- );
+ "INSERT INTO %Q." LEGACY_SCHEMA_TABLE " VALUES('index',%Q,%Q,#%d,%Q);",
+ db->aDb[iDb].zDbSName,
+ pIndex->zName,
+ pTab->zName,
+ iMem,
+ zStmt
+ );
sqlcipher_sqlite3DbFree(db, zStmt);
/* Fill the index with data and reparse the schema. Code an OP_Expire
@@ -119640,7 +124844,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3CreateIndex(
sqlcipher_sqlite3RefillIndex(pParse, pIndex, iMem);
sqlcipher_sqlite3ChangeCookie(pParse, iDb);
sqlcipher_sqlite3VdbeAddParseSchemaOp(v, iDb,
- sqlcipher_sqlite3MPrintf(db, "name='%q' AND type='index'", pIndex->zName));
+ sqlcipher_sqlite3MPrintf(db, "name='%q' AND type='index'", pIndex->zName), 0);
sqlcipher_sqlite3VdbeAddOp2(v, OP_Expire, 0, 1);
}
@@ -119661,8 +124865,12 @@ SQLITE_PRIVATE void sqlcipher_sqlite3CreateIndex(
/* Clean up before exiting */
exit_create_index:
if( pIndex ) sqlcipher_sqlite3FreeIndex(db, pIndex);
- if( pTab ){ /* Ensure all REPLACE indexes are at the end of the list */
- Index **ppFrom = &pTab->pIndex;
+ if( pTab ){
+ /* Ensure all REPLACE indexes on pTab are at the end of the pIndex list.
+ ** The list was already ordered when this routine was entered, so at this
+ ** point at most a single index (the newly added index) will be out of
+ ** order. So we have to reorder at most one index. */
+ Index **ppFrom;
Index *pThis;
for(ppFrom=&pTab->pIndex; (pThis = *ppFrom)!=0; ppFrom=&pThis->pNext){
Index *pNext;
@@ -119675,6 +124883,16 @@ exit_create_index:
}
break;
}
+#ifdef SQLITE_DEBUG
+ /* Verify that all REPLACE indexes really are now at the end
+ ** of the index list. In other words, no other index type ever
+ ** comes after a REPLACE index on the list. */
+ for(pThis = pTab->pIndex; pThis; pThis=pThis->pNext){
+ assert( pThis->onError!=OE_Replace
+ || pThis->pNext==0
+ || pThis->pNext->onError==OE_Replace );
+ }
+#endif
}
sqlcipher_sqlite3ExprDelete(db, pPIWhere);
sqlcipher_sqlite3ExprListDelete(db, pList);
@@ -119726,7 +124944,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3DefaultRowEst(Index *pIdx){
if( x<99 ){
pIdx->pTable->nRowLogEst = x = 99;
}
- if( pIdx->pPartIdxWhere!=0 ) x -= 10; assert( 10==sqlcipher_sqlite3LogEst(2) );
+ if( pIdx->pPartIdxWhere!=0 ){ x -= 10; assert( 10==sqlcipher_sqlite3LogEst(2) ); }
a[0] = x;
/* Estimate that a[1] is 10, a[2] is 9, a[3] is 8, a[4] is 7, a[5] is
@@ -119750,10 +124968,10 @@ SQLITE_PRIVATE void sqlcipher_sqlite3DropIndex(Parse *pParse, SrcList *pName, in
sqlcipher_sqlite3 *db = pParse->db;
int iDb;
- assert( pParse->nErr==0 ); /* Never called with prior errors */
if( db->mallocFailed ){
goto exit_drop_index;
}
+ assert( pParse->nErr==0 ); /* Never called with prior non-OOM errors */
assert( pName->nSrc==1 );
if( SQLITE_OK!=sqlcipher_sqlite3ReadSchema(pParse) ){
goto exit_drop_index;
@@ -119761,9 +124979,10 @@ SQLITE_PRIVATE void sqlcipher_sqlite3DropIndex(Parse *pParse, SrcList *pName, in
pIndex = sqlcipher_sqlite3FindIndex(db, pName->a[0].zName, pName->a[0].zDatabase);
if( pIndex==0 ){
if( !ifExists ){
- sqlcipher_sqlite3ErrorMsg(pParse, "no such index: %S", pName, 0);
+ sqlcipher_sqlite3ErrorMsg(pParse, "no such index: %S", pName->a);
}else{
sqlcipher_sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase);
+ sqlcipher_sqlite3ForceNotReadOnly(pParse);
}
pParse->checkSchema = 1;
goto exit_drop_index;
@@ -119783,7 +125002,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3DropIndex(Parse *pParse, SrcList *pName, in
if( sqlcipher_sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){
goto exit_drop_index;
}
- if( !OMIT_TEMPDB && iDb ) code = SQLITE_DROP_TEMP_INDEX;
+ if( !OMIT_TEMPDB && iDb==1 ) code = SQLITE_DROP_TEMP_INDEX;
if( sqlcipher_sqlite3AuthCheck(pParse, code, pIndex->zName, pTab->zName, zDb) ){
goto exit_drop_index;
}
@@ -119795,7 +125014,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3DropIndex(Parse *pParse, SrcList *pName, in
if( v ){
sqlcipher_sqlite3BeginWriteOperation(pParse, 1, iDb);
sqlcipher_sqlite3NestedParse(pParse,
- "DELETE FROM %Q." DFLT_SCHEMA_TABLE " WHERE name=%Q AND type='index'",
+ "DELETE FROM %Q." LEGACY_SCHEMA_TABLE " WHERE name=%Q AND type='index'",
db->aDb[iDb].zDbSName, pIndex->zName
);
sqlcipher_sqlite3ClearStatTables(pParse, iDb, "idx", pIndex->zName);
@@ -119861,18 +125080,17 @@ SQLITE_PRIVATE IdList *sqlcipher_sqlite3IdListAppend(Parse *pParse, IdList *pLis
if( pList==0 ){
pList = sqlcipher_sqlite3DbMallocZero(db, sizeof(IdList) );
if( pList==0 ) return 0;
+ }else{
+ IdList *pNew;
+ pNew = sqlcipher_sqlite3DbRealloc(db, pList,
+ sizeof(IdList) + pList->nId*sizeof(pList->a));
+ if( pNew==0 ){
+ sqlcipher_sqlite3IdListDelete(db, pList);
+ return 0;
+ }
+ pList = pNew;
}
- pList->a = sqlcipher_sqlite3ArrayAllocate(
- db,
- pList->a,
- sizeof(pList->a[0]),
- &pList->nId,
- &i
- );
- if( i<0 ){
- sqlcipher_sqlite3IdListDelete(db, pList);
- return 0;
- }
+ i = pList->nId++;
pList->a[i].zName = sqlcipher_sqlite3NameFromToken(db, pToken);
if( IN_RENAME_OBJECT && pList->a[i].zName ){
sqlcipher_sqlite3RenameTokenMap(pParse, (void*)pList->a[i].zName, pToken);
@@ -119886,10 +125104,10 @@ SQLITE_PRIVATE IdList *sqlcipher_sqlite3IdListAppend(Parse *pParse, IdList *pLis
SQLITE_PRIVATE void sqlcipher_sqlite3IdListDelete(sqlcipher_sqlite3 *db, IdList *pList){
int i;
if( pList==0 ) return;
+ assert( pList->eU4!=EU4_EXPR ); /* EU4_EXPR mode is not currently used */
for(i=0; i<pList->nId; i++){
sqlcipher_sqlite3DbFree(db, pList->a[i].zName);
}
- sqlcipher_sqlite3DbFree(db, pList->a);
sqlcipher_sqlite3DbFreeNN(db, pList);
}
@@ -119899,7 +125117,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3IdListDelete(sqlcipher_sqlite3 *db, IdList
*/
SQLITE_PRIVATE int sqlcipher_sqlite3IdListIndex(IdList *pList, const char *zName){
int i;
- if( pList==0 ) return -1;
+ assert( pList!=0 );
for(i=0; i<pList->nId; i++){
if( sqlcipher_sqlite3StrICmp(pList->a[i].zName, zName)==0 ) return i;
}
@@ -120033,7 +125251,7 @@ SQLITE_PRIVATE SrcList *sqlcipher_sqlite3SrcListAppend(
Token *pTable, /* Table to append */
Token *pDatabase /* Database of the table */
){
- struct SrcList_item *pItem;
+ SrcItem *pItem;
sqlcipher_sqlite3 *db;
assert( pDatabase==0 || pTable!=0 ); /* Cannot have C without B */
assert( pParse!=0 );
@@ -120074,9 +125292,9 @@ SQLITE_PRIVATE SrcList *sqlcipher_sqlite3SrcListAppend(
*/
SQLITE_PRIVATE void sqlcipher_sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){
int i;
- struct SrcList_item *pItem;
- assert(pList || pParse->db->mallocFailed );
- if( pList ){
+ SrcItem *pItem;
+ assert( pList || pParse->db->mallocFailed );
+ if( ALWAYS(pList) ){
for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
if( pItem->iCursor>=0 ) continue;
pItem->iCursor = pParse->nTab++;
@@ -120092,7 +125310,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3SrcListAssignCursors(Parse *pParse, SrcList
*/
SQLITE_PRIVATE void sqlcipher_sqlite3SrcListDelete(sqlcipher_sqlite3 *db, SrcList *pList){
int i;
- struct SrcList_item *pItem;
+ SrcItem *pItem;
if( pList==0 ) return;
for(pItem=pList->a, i=0; i<pList->nSrc; i++, pItem++){
if( pItem->zDatabase ) sqlcipher_sqlite3DbFreeNN(db, pItem->zDatabase);
@@ -120102,8 +125320,11 @@ SQLITE_PRIVATE void sqlcipher_sqlite3SrcListDelete(sqlcipher_sqlite3 *db, SrcLis
if( pItem->fg.isTabFunc ) sqlcipher_sqlite3ExprListDelete(db, pItem->u1.pFuncArg);
sqlcipher_sqlite3DeleteTable(db, pItem->pTab);
if( pItem->pSelect ) sqlcipher_sqlite3SelectDelete(db, pItem->pSelect);
- if( pItem->pOn ) sqlcipher_sqlite3ExprDelete(db, pItem->pOn);
- if( pItem->pUsing ) sqlcipher_sqlite3IdListDelete(db, pItem->pUsing);
+ if( pItem->fg.isUsing ){
+ sqlcipher_sqlite3IdListDelete(db, pItem->u3.pUsing);
+ }else if( pItem->u3.pOn ){
+ sqlcipher_sqlite3ExprDelete(db, pItem->u3.pOn);
+ }
}
sqlcipher_sqlite3DbFreeNN(db, pList);
}
@@ -120131,14 +125352,13 @@ SQLITE_PRIVATE SrcList *sqlcipher_sqlite3SrcListAppendFromTerm(
Token *pDatabase, /* Name of the database containing pTable */
Token *pAlias, /* The right-hand side of the AS subexpression */
Select *pSubquery, /* A subquery used in place of a table name */
- Expr *pOn, /* The ON clause of a join */
- IdList *pUsing /* The USING clause of a join */
+ OnOrUsing *pOnUsing /* Either the ON clause or the USING clause */
){
- struct SrcList_item *pItem;
+ SrcItem *pItem;
sqlcipher_sqlite3 *db = pParse->db;
- if( !p && (pOn || pUsing) ){
+ if( !p && pOnUsing!=0 && (pOnUsing->pOn || pOnUsing->pUsing) ){
sqlcipher_sqlite3ErrorMsg(pParse, "a JOIN clause is required before %s",
- (pOn ? "ON" : "USING")
+ (pOnUsing->pOn ? "ON" : "USING")
);
goto append_from_error;
}
@@ -120158,15 +125378,27 @@ SQLITE_PRIVATE SrcList *sqlcipher_sqlite3SrcListAppendFromTerm(
if( pAlias->n ){
pItem->zAlias = sqlcipher_sqlite3NameFromToken(db, pAlias);
}
- pItem->pSelect = pSubquery;
- pItem->pOn = pOn;
- pItem->pUsing = pUsing;
+ if( pSubquery ){
+ pItem->pSelect = pSubquery;
+ if( pSubquery->selFlags & SF_NestedFrom ){
+ pItem->fg.isNestedFrom = 1;
+ }
+ }
+ assert( pOnUsing==0 || pOnUsing->pOn==0 || pOnUsing->pUsing==0 );
+ assert( pItem->fg.isUsing==0 );
+ if( pOnUsing==0 ){
+ pItem->u3.pOn = 0;
+ }else if( pOnUsing->pUsing ){
+ pItem->fg.isUsing = 1;
+ pItem->u3.pUsing = pOnUsing->pUsing;
+ }else{
+ pItem->u3.pOn = pOnUsing->pOn;
+ }
return p;
- append_from_error:
+append_from_error:
assert( p==0 );
- sqlcipher_sqlite3ExprDelete(db, pOn);
- sqlcipher_sqlite3IdListDelete(db, pUsing);
+ sqlcipher_sqlite3ClearOnOrUsing(db, pOnUsing);
sqlcipher_sqlite3SelectDelete(db, pSubquery);
return 0;
}
@@ -120178,7 +125410,7 @@ SQLITE_PRIVATE SrcList *sqlcipher_sqlite3SrcListAppendFromTerm(
SQLITE_PRIVATE void sqlcipher_sqlite3SrcListIndexedBy(Parse *pParse, SrcList *p, Token *pIndexedBy){
assert( pIndexedBy!=0 );
if( p && pIndexedBy->n>0 ){
- struct SrcList_item *pItem;
+ SrcItem *pItem;
assert( p->nSrc>0 );
pItem = &p->a[p->nSrc-1];
assert( pItem->fg.notIndexed==0 );
@@ -120191,6 +125423,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3SrcListIndexedBy(Parse *pParse, SrcList *p,
}else{
pItem->u1.zIndexedBy = sqlcipher_sqlite3NameFromToken(pParse->db, pIndexedBy);
pItem->fg.isIndexedBy = 1;
+ assert( pItem->fg.isCte==0 ); /* No collision on union u2 */
}
}
}
@@ -120208,8 +125441,9 @@ SQLITE_PRIVATE SrcList *sqlcipher_sqlite3SrcListAppendList(Parse *pParse, SrcLis
sqlcipher_sqlite3SrcListDelete(pParse->db, p2);
}else{
p1 = pNew;
- memcpy(&p1->a[1], p2->a, p2->nSrc*sizeof(struct SrcList_item));
+ memcpy(&p1->a[1], p2->a, p2->nSrc*sizeof(SrcItem));
sqlcipher_sqlite3DbFree(pParse->db, p2);
+ p1->a[0].fg.jointype |= (JT_LTORJ & p1->a[1].fg.jointype);
}
}
return p1;
@@ -120221,7 +125455,7 @@ SQLITE_PRIVATE SrcList *sqlcipher_sqlite3SrcListAppendList(Parse *pParse, SrcLis
*/
SQLITE_PRIVATE void sqlcipher_sqlite3SrcListFuncArgs(Parse *pParse, SrcList *p, ExprList *pList){
if( p ){
- struct SrcList_item *pItem = &p->a[p->nSrc-1];
+ SrcItem *pItem = &p->a[p->nSrc-1];
assert( pItem->fg.notIndexed==0 );
assert( pItem->fg.isIndexedBy==0 );
assert( pItem->fg.isTabFunc==0 );
@@ -120246,14 +125480,34 @@ SQLITE_PRIVATE void sqlcipher_sqlite3SrcListFuncArgs(Parse *pParse, SrcList *p,
** The operator is "natural cross join". The A and B operands are stored
** in p->a[0] and p->a[1], respectively. The parser initially stores the
** operator with A. This routine shifts that operator over to B.
+**
+** Additional changes:
+**
+** * All tables to the left of the right-most RIGHT JOIN are tagged with
+** JT_LTORJ (mnemonic: Left Table Of Right Join) so that the
+** code generator can easily tell that the table is part of
+** the left operand of at least one RIGHT JOIN.
*/
-SQLITE_PRIVATE void sqlcipher_sqlite3SrcListShiftJoinType(SrcList *p){
- if( p ){
- int i;
- for(i=p->nSrc-1; i>0; i--){
- p->a[i].fg.jointype = p->a[i-1].fg.jointype;
- }
+SQLITE_PRIVATE void sqlcipher_sqlite3SrcListShiftJoinType(Parse *pParse, SrcList *p){
+ (void)pParse;
+ if( p && p->nSrc>1 ){
+ int i = p->nSrc-1;
+ u8 allFlags = 0;
+ do{
+ allFlags |= p->a[i].fg.jointype = p->a[i-1].fg.jointype;
+ }while( (--i)>0 );
p->a[0].fg.jointype = 0;
+
+ /* All terms to the left of a RIGHT JOIN should be tagged with the
+ ** JT_LTORJ flags */
+ if( allFlags & JT_RIGHT ){
+ for(i=p->nSrc-1; ALWAYS(i>0) && (p->a[i].fg.jointype&JT_RIGHT)==0; i--){}
+ i--;
+ assert( i>=0 );
+ do{
+ p->a[i].fg.jointype |= JT_LTORJ;
+ }while( (--i)>=0 );
+ }
}
}
@@ -120376,7 +125630,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3OpenTempDatabase(Parse *pParse){
static void sqlcipher_sqlite3CodeVerifySchemaAtToplevel(Parse *pToplevel, int iDb){
assert( iDb>=0 && iDb<pToplevel->db->nDb );
assert( pToplevel->db->aDb[iDb].pBt!=0 || iDb==1 );
- assert( iDb<SQLITE_MAX_ATTACHED+2 );
+ assert( iDb<SQLITE_MAX_DB );
assert( sqlcipher_sqlite3SchemaMutexHeld(pToplevel->db, iDb, 0) );
if( DbMaskTest(pToplevel->cookieMask, iDb)==0 ){
DbMaskSet(pToplevel->cookieMask, iDb);
@@ -120503,7 +125757,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3UniqueConstraint(
for(j=0; j<pIdx->nKeyCol; j++){
char *zCol;
assert( pIdx->aiColumn[j]>=0 );
- zCol = pTab->aCol[pIdx->aiColumn[j]].zName;
+ zCol = pTab->aCol[pIdx->aiColumn[j]].zCnName;
if( j ) sqlcipher_sqlite3_str_append(&errMsg, ", ", 2);
sqlcipher_sqlite3_str_appendall(&errMsg, pTab->zName);
sqlcipher_sqlite3_str_append(&errMsg, ".", 1);
@@ -120530,7 +125784,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3RowidConstraint(
int rc;
if( pTab->iPKey>=0 ){
zMsg = sqlcipher_sqlite3MPrintf(pParse->db, "%s.%s", pTab->zName,
- pTab->aCol[pTab->iPKey].zName);
+ pTab->aCol[pTab->iPKey].zCnName);
rc = SQLITE_CONSTRAINT_PRIMARYKEY;
}else{
zMsg = sqlcipher_sqlite3MPrintf(pParse->db, "%s.rowid", pTab->zName);
@@ -120719,23 +125973,75 @@ SQLITE_PRIVATE KeyInfo *sqlcipher_sqlite3KeyInfoOfIndex(Parse *pParse, Index *pI
#ifndef SQLITE_OMIT_CTE
/*
+** Create a new CTE object
+*/
+SQLITE_PRIVATE Cte *sqlcipher_sqlite3CteNew(
+ Parse *pParse, /* Parsing context */
+ Token *pName, /* Name of the common-table */
+ ExprList *pArglist, /* Optional column name list for the table */
+ Select *pQuery, /* Query used to initialize the table */
+ u8 eM10d /* The MATERIALIZED flag */
+){
+ Cte *pNew;
+ sqlcipher_sqlite3 *db = pParse->db;
+
+ pNew = sqlcipher_sqlite3DbMallocZero(db, sizeof(*pNew));
+ assert( pNew!=0 || db->mallocFailed );
+
+ if( db->mallocFailed ){
+ sqlcipher_sqlite3ExprListDelete(db, pArglist);
+ sqlcipher_sqlite3SelectDelete(db, pQuery);
+ }else{
+ pNew->pSelect = pQuery;
+ pNew->pCols = pArglist;
+ pNew->zName = sqlcipher_sqlite3NameFromToken(pParse->db, pName);
+ pNew->eM10d = eM10d;
+ }
+ return pNew;
+}
+
+/*
+** Clear information from a Cte object, but do not deallocate storage
+** for the object itself.
+*/
+static void cteClear(sqlcipher_sqlite3 *db, Cte *pCte){
+ assert( pCte!=0 );
+ sqlcipher_sqlite3ExprListDelete(db, pCte->pCols);
+ sqlcipher_sqlite3SelectDelete(db, pCte->pSelect);
+ sqlcipher_sqlite3DbFree(db, pCte->zName);
+}
+
+/*
+** Free the contents of the CTE object passed as the second argument.
+*/
+SQLITE_PRIVATE void sqlcipher_sqlite3CteDelete(sqlcipher_sqlite3 *db, Cte *pCte){
+ assert( pCte!=0 );
+ cteClear(db, pCte);
+ sqlcipher_sqlite3DbFree(db, pCte);
+}
+
+/*
** This routine is invoked once per CTE by the parser while parsing a
-** WITH clause.
+** WITH clause. The CTE described by teh third argument is added to
+** the WITH clause of the second argument. If the second argument is
+** NULL, then a new WITH argument is created.
*/
SQLITE_PRIVATE With *sqlcipher_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 */
+ Cte *pCte /* CTE to add to the WITH clause */
){
sqlcipher_sqlite3 *db = pParse->db;
With *pNew;
char *zName;
+ if( pCte==0 ){
+ return pWith;
+ }
+
/* Check that the CTE name is unique within this WITH clause. If
** not, store an error in the Parse structure. */
- zName = sqlcipher_sqlite3NameFromToken(pParse->db, pName);
+ zName = pCte->zName;
if( zName && pWith ){
int i;
for(i=0; i<pWith->nCte; i++){
@@ -120754,16 +126060,11 @@ SQLITE_PRIVATE With *sqlcipher_sqlite3WithAdd(
assert( (pNew!=0 && zName!=0) || db->mallocFailed );
if( db->mallocFailed ){
- sqlcipher_sqlite3ExprListDelete(db, pArglist);
- sqlcipher_sqlite3SelectDelete(db, pQuery);
- sqlcipher_sqlite3DbFree(db, zName);
+ sqlcipher_sqlite3CteDelete(db, pCte);
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].zCteErr = 0;
- pNew->nCte++;
+ pNew->a[pNew->nCte++] = *pCte;
+ sqlcipher_sqlite3DbFree(db, pCte);
}
return pNew;
@@ -120776,10 +126077,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3WithDelete(sqlcipher_sqlite3 *db, With *pWi
if( pWith ){
int i;
for(i=0; i<pWith->nCte; i++){
- struct Cte *pCte = &pWith->a[i];
- sqlcipher_sqlite3ExprListDelete(db, pCte->pCols);
- sqlcipher_sqlite3SelectDelete(db, pCte->pSelect);
- sqlcipher_sqlite3DbFree(db, pCte->zName);
+ cteClear(db, &pWith->a[i]);
}
sqlcipher_sqlite3DbFree(db, pWith);
}
@@ -121127,6 +126425,7 @@ SQLITE_PRIVATE FuncDef *sqlcipher_sqlite3FunctionSearch(
){
FuncDef *p;
for(p=sqlcipher_sqlite3BuiltinFunctions.a[h]; p; p=p->u.pHash){
+ assert( p->funcFlags & SQLITE_FUNC_BUILTIN );
if( sqlcipher_sqlite3StrICmp(p->zName, zFunc)==0 ){
return p;
}
@@ -121147,7 +126446,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3InsertBuiltinFuncs(
const char *zName = aDef[i].zName;
int nName = sqlcipher_sqlite3Strlen30(zName);
int h = SQLITE_FUNC_HASH(zName[0], nName);
- assert( zName[0]>='a' && zName[0]<='z' );
+ assert( aDef[i].funcFlags & SQLITE_FUNC_BUILTIN );
pOther = sqlcipher_sqlite3FunctionSearch(h, zName);
if( pOther ){
assert( pOther!=&aDef[i] && pOther->pNext!=&aDef[i] );
@@ -121358,7 +126657,7 @@ SQLITE_PRIVATE Schema *sqlcipher_sqlite3SchemaGet(sqlcipher_sqlite3 *db, Btree *
**
*/
SQLITE_PRIVATE Table *sqlcipher_sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
- struct SrcList_item *pItem = pSrc->a;
+ SrcItem *pItem = pSrc->a;
Table *pTab;
assert( pItem && pSrc->nSrc>=1 );
pTab = sqlcipher_sqlite3LocateTableItem(pParse, 0, pItem);
@@ -121366,13 +126665,23 @@ SQLITE_PRIVATE Table *sqlcipher_sqlite3SrcListLookup(Parse *pParse, SrcList *pSr
pItem->pTab = pTab;
if( pTab ){
pTab->nTabRef++;
- }
- if( sqlcipher_sqlite3IndexedByLookup(pParse, pItem) ){
- pTab = 0;
+ if( pItem->fg.isIndexedBy && sqlcipher_sqlite3IndexedByLookup(pParse, pItem) ){
+ pTab = 0;
+ }
}
return pTab;
}
+/* Generate byte-code that will report the number of rows modified
+** by a DELETE, INSERT, or UPDATE statement.
+*/
+SQLITE_PRIVATE void sqlcipher_sqlite3CodeChangeCount(Vdbe *v, int regCounter, const char *zColName){
+ sqlcipher_sqlite3VdbeAddOp0(v, OP_FkCheck);
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_ResultRow, regCounter, 1);
+ sqlcipher_sqlite3VdbeSetNumCols(v, 1);
+ sqlcipher_sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zColName, SQLITE_STATIC);
+}
+
/* Return true if table pTab is read-only.
**
** A table is read-only if any of the following are true:
@@ -121413,7 +126722,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3IsReadOnly(Parse *pParse, Table *pTab, int v
return 1;
}
#ifndef SQLITE_OMIT_VIEW
- if( !viewOk && pTab->pSelect ){
+ if( !viewOk && IsView(pTab) ){
sqlcipher_sqlite3ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName);
return 1;
}
@@ -121447,8 +126756,8 @@ SQLITE_PRIVATE void sqlcipher_sqlite3MaterializeView(
assert( pFrom->nSrc==1 );
pFrom->a[0].zName = sqlcipher_sqlite3DbStrDup(db, pView->zName);
pFrom->a[0].zDatabase = sqlcipher_sqlite3DbStrDup(db, db->aDb[iDb].zDbSName);
- assert( pFrom->a[0].pOn==0 );
- assert( pFrom->a[0].pUsing==0 );
+ assert( pFrom->a[0].fg.isUsing==0 );
+ assert( pFrom->a[0].u3.pOn==0 );
}
pSel = sqlcipher_sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, pOrderBy,
SF_IncludeHidden, pLimit);
@@ -121517,13 +126826,13 @@ SQLITE_PRIVATE Expr *sqlcipher_sqlite3LimitWhere(
}else{
Index *pPk = sqlcipher_sqlite3PrimaryKeyIndex(pTab);
if( pPk->nKeyCol==1 ){
- const char *zName = pTab->aCol[pPk->aiColumn[0]].zName;
+ const char *zName = pTab->aCol[pPk->aiColumn[0]].zCnName;
pLhs = sqlcipher_sqlite3Expr(db, TK_ID, zName);
pEList = sqlcipher_sqlite3ExprListAppend(pParse, 0, sqlcipher_sqlite3Expr(db, TK_ID, zName));
}else{
int i;
for(i=0; i<pPk->nKeyCol; i++){
- Expr *p = sqlcipher_sqlite3Expr(db, TK_ID, pTab->aCol[pPk->aiColumn[i]].zName);
+ Expr *p = sqlcipher_sqlite3Expr(db, TK_ID, pTab->aCol[pPk->aiColumn[i]].zCnName);
pEList = sqlcipher_sqlite3ExprListAppend(pParse, pEList, p);
}
pLhs = sqlcipher_sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
@@ -121536,9 +126845,16 @@ SQLITE_PRIVATE Expr *sqlcipher_sqlite3LimitWhere(
/* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree
** and the SELECT subtree. */
pSrc->a[0].pTab = 0;
- pSelectSrc = sqlcipher_sqlite3SrcListDup(pParse->db, pSrc, 0);
+ pSelectSrc = sqlcipher_sqlite3SrcListDup(db, pSrc, 0);
pSrc->a[0].pTab = pTab;
- pSrc->a[0].pIBIndex = 0;
+ if( pSrc->a[0].fg.isIndexedBy ){
+ assert( pSrc->a[0].fg.isCte==0 );
+ pSrc->a[0].u2.pIBIndex = 0;
+ pSrc->a[0].fg.isIndexedBy = 0;
+ sqlcipher_sqlite3DbFree(db, pSrc->a[0].u1.zIndexedBy);
+ }else if( pSrc->a[0].fg.isCte ){
+ pSrc->a[0].u2.pCteUse->nUse++;
+ }
/* generate the SELECT expression tree. */
pSelect = sqlcipher_sqlite3SelectNew(pParse, pEList, pSelectSrc, pWhere, 0 ,0,
@@ -121605,12 +126921,13 @@ SQLITE_PRIVATE void sqlcipher_sqlite3DeleteFrom(
memset(&sContext, 0, sizeof(sContext));
db = pParse->db;
- if( pParse->nErr || db->mallocFailed ){
+ assert( db->pParse==pParse );
+ if( pParse->nErr ){
goto delete_from_cleanup;
}
+ assert( db->mallocFailed==0 );
assert( pTabList->nSrc==1 );
-
/* Locate the table which we want to delete. This table has to be
** put in an SrcList structure because some of the subroutines we
** will be calling are designed to work with multiple tables and expect
@@ -121624,7 +126941,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3DeleteFrom(
*/
#ifndef SQLITE_OMIT_TRIGGER
pTrigger = sqlcipher_sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
- isView = pTab->pSelect!=0;
+ isView = IsView(pTab);
#else
# define pTrigger 0
# define isView 0
@@ -121635,6 +126952,14 @@ SQLITE_PRIVATE void sqlcipher_sqlite3DeleteFrom(
# define isView 0
#endif
+#if TREETRACE_ENABLED
+ if( sqlcipher_sqlite3TreeTrace & 0x10000 ){
+ sqlcipher_sqlite3TreeViewLine(0, "In sqlcipher_sqlite3Delete() at %s:%d", __FILE__, __LINE__);
+ sqlcipher_sqlite3TreeViewDelete(pParse->pWith, pTabList, pWhere,
+ pOrderBy, pLimit, pTrigger);
+ }
+#endif
+
#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
if( !isView ){
pWhere = sqlcipher_sqlite3LimitWhere(
@@ -121716,6 +127041,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3DeleteFrom(
if( (db->flags & SQLITE_CountRows)!=0
&& !pParse->nested
&& !pParse->pTriggerTab
+ && !pParse->bReturning
){
memCnt = ++pParse->nMem;
sqlcipher_sqlite3VdbeAddOp2(v, OP_Integer, 0, memCnt);
@@ -121750,6 +127076,9 @@ SQLITE_PRIVATE void sqlcipher_sqlite3DeleteFrom(
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
assert( pIdx->pSchema==pTab->pSchema );
sqlcipher_sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb);
+ if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){
+ sqlcipher_sqlite3VdbeChangeP3(v, -1, memCnt ? memCnt : -1);
+ }
}
}else
#endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */
@@ -121784,7 +127113,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3DeleteFrom(
** ONEPASS_SINGLE: One-pass approach - at most one row deleted.
** ONEPASS_MULTI: One-pass approach - any number of rows may be deleted.
*/
- pWInfo = sqlcipher_sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, wcf, iTabCur+1);
+ pWInfo = sqlcipher_sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0,0,wcf,iTabCur+1);
if( pWInfo==0 ) goto delete_from_cleanup;
eOnePass = sqlcipher_sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
assert( IsVirtual(pTab)==0 || eOnePass!=ONEPASS_MULTI );
@@ -121870,7 +127199,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3DeleteFrom(
if( eOnePass!=ONEPASS_OFF ){
assert( nKey==nPk ); /* OP_Found will use an unpacked key */
if( !IsVirtual(pTab) && aToOpen[iDataCur-iTabCur] ){
- assert( pPk!=0 || pTab->pSelect!=0 );
+ assert( pPk!=0 || IsView(pTab) );
sqlcipher_sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, addrBypass, iKey, nKey);
VdbeCoverage(v);
}
@@ -121937,9 +127266,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3DeleteFrom(
** invoke the callback function.
*/
if( memCnt ){
- sqlcipher_sqlite3VdbeAddOp2(v, OP_ResultRow, memCnt, 1);
- sqlcipher_sqlite3VdbeSetNumCols(v, 1);
- sqlcipher_sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted", SQLITE_STATIC);
+ sqlcipher_sqlite3CodeChangeCount(v, memCnt, "rows deleted");
}
delete_from_cleanup:
@@ -122104,7 +127431,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3GenerateRowDelete(
** the update-hook is not invoked for rows removed by REPLACE, but the
** pre-update-hook is.
*/
- if( pTab->pSelect==0 ){
+ if( !IsView(pTab) ){
u8 p5 = 0;
sqlcipher_sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur,0,iIdxNoSeek);
sqlcipher_sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, (count?OPFLAG_NCHANGE:0));
@@ -122261,13 +127588,15 @@ SQLITE_PRIVATE int sqlcipher_sqlite3GenerateIndexKey(
continue;
}
sqlcipher_sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iDataCur, 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 */
- sqlcipher_sqlite3VdbeDeletePriorOpcode(v, OP_RealAffinity);
+ if( pIdx->aiColumn[j]>=0 ){
+ /* 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 */
+ sqlcipher_sqlite3VdbeDeletePriorOpcode(v, OP_RealAffinity);
+ }
}
if( regOut ){
sqlcipher_sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regOut);
@@ -122388,6 +127717,18 @@ static void typeofFunc(
sqlcipher_sqlite3_result_text(context, azType[i], -1, SQLITE_STATIC);
}
+/* subtype(X)
+**
+** Return the subtype of X
+*/
+static void subtypeFunc(
+ sqlcipher_sqlite3_context *context,
+ int argc,
+ sqlcipher_sqlite3_value **argv
+){
+ UNUSED_PARAMETER(argc);
+ sqlcipher_sqlite3_result_int(context, sqlcipher_sqlite3_value_subtype(argv[0]));
+}
/*
** Implementation of the length() function
@@ -122549,7 +127890,7 @@ endInstrOOM:
}
/*
-** Implementation of the printf() function.
+** Implementation of the printf() (a.k.a. format()) SQL function.
*/
static void printfFunc(
sqlcipher_sqlite3_context *context,
@@ -122862,9 +128203,9 @@ static void last_insert_rowid(
/*
** Implementation of the changes() SQL function.
**
-** IMP: R-62073-11209 The changes() SQL function is a wrapper
-** around the sqlcipher_sqlite3_changes() C/C++ function and hence follows the same
-** rules for counting changes.
+** IMP: R-32760-32347 The changes() SQL function is a wrapper
+** around the sqlcipher_sqlite3_changes64() C/C++ function and hence follows the
+** same rules for counting changes.
*/
static void changes(
sqlcipher_sqlite3_context *context,
@@ -122873,12 +128214,12 @@ static void changes(
){
sqlcipher_sqlite3 *db = sqlcipher_sqlite3_context_db_handle(context);
UNUSED_PARAMETER2(NotUsed, NotUsed2);
- sqlcipher_sqlite3_result_int(context, sqlcipher_sqlite3_changes(db));
+ sqlcipher_sqlite3_result_int64(context, sqlcipher_sqlite3_changes64(db));
}
/*
** Implementation of the total_changes() SQL function. The return value is
-** the same as the sqlcipher_sqlite3_total_changes() API function.
+** the same as the sqlcipher_sqlite3_total_changes64() API function.
*/
static void total_changes(
sqlcipher_sqlite3_context *context,
@@ -122887,9 +128228,9 @@ static void total_changes(
){
sqlcipher_sqlite3 *db = sqlcipher_sqlite3_context_db_handle(context);
UNUSED_PARAMETER2(NotUsed, NotUsed2);
- /* IMP: R-52756-41993 This function is a wrapper around the
- ** sqlcipher_sqlite3_total_changes() C/C++ interface. */
- sqlcipher_sqlite3_result_int(context, sqlcipher_sqlite3_total_changes(db));
+ /* IMP: R-11217-42568 This function is a wrapper around the
+ ** sqlcipher_sqlite3_total_changes64() C/C++ interface. */
+ sqlcipher_sqlite3_result_int64(context, sqlcipher_sqlite3_total_changes64(db));
}
/*
@@ -122985,7 +128326,8 @@ static int patternCompare(
/* Skip over multiple "*" characters in the pattern. If there
** are also "?" characters, skip those as well, but consume a
** single character of the input string for each "?" skipped */
- while( (c=Utf8Read(zPattern)) == matchAll || c == matchOne ){
+ while( (c=Utf8Read(zPattern)) == matchAll
+ || (c == matchOne && matchOne!=0) ){
if( c==matchOne && sqlcipher_sqlite3Utf8Read(&zString)==0 ){
return SQLITE_NOWILDCARDMATCH;
}
@@ -123317,39 +128659,42 @@ static const char hexdigits[] = {
};
/*
-** Implementation of the QUOTE() function. This function takes a single
-** argument. If the argument is numeric, the return value is the same as
-** the argument. If the argument is NULL, the return value is the string
-** "NULL". Otherwise, the argument is enclosed in single quotes with
-** single-quote escapes.
+** Append to pStr text that is the SQL literal representation of the
+** value contained in pValue.
*/
-static void quoteFunc(sqlcipher_sqlite3_context *context, int argc, sqlcipher_sqlite3_value **argv){
- assert( argc==1 );
- UNUSED_PARAMETER(argc);
- switch( sqlcipher_sqlite3_value_type(argv[0]) ){
+SQLITE_PRIVATE void sqlcipher_sqlite3QuoteValue(StrAccum *pStr, sqlcipher_sqlite3_value *pValue){
+ /* As currently implemented, the string must be initially empty.
+ ** we might relax this requirement in the future, but that will
+ ** require enhancements to the implementation. */
+ assert( pStr!=0 && pStr->nChar==0 );
+
+ switch( sqlcipher_sqlite3_value_type(pValue) ){
case SQLITE_FLOAT: {
double r1, r2;
- char zBuf[50];
- r1 = sqlcipher_sqlite3_value_double(argv[0]);
- sqlcipher_sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.15g", r1);
- sqlcipher_sqlite3AtoF(zBuf, &r2, 20, SQLITE_UTF8);
- if( r1!=r2 ){
- sqlcipher_sqlite3_snprintf(sizeof(zBuf), zBuf, "%!.20e", r1);
+ const char *zVal;
+ r1 = sqlcipher_sqlite3_value_double(pValue);
+ sqlcipher_sqlite3_str_appendf(pStr, "%!.15g", r1);
+ zVal = sqlcipher_sqlite3_str_value(pStr);
+ if( zVal ){
+ sqlcipher_sqlite3AtoF(zVal, &r2, pStr->nChar, SQLITE_UTF8);
+ if( r1!=r2 ){
+ sqlcipher_sqlite3_str_reset(pStr);
+ sqlcipher_sqlite3_str_appendf(pStr, "%!.20e", r1);
+ }
}
- sqlcipher_sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
break;
}
case SQLITE_INTEGER: {
- sqlcipher_sqlite3_result_value(context, argv[0]);
+ sqlcipher_sqlite3_str_appendf(pStr, "%lld", sqlcipher_sqlite3_value_int64(pValue));
break;
}
case SQLITE_BLOB: {
- char *zText = 0;
- char const *zBlob = sqlcipher_sqlite3_value_blob(argv[0]);
- int nBlob = sqlcipher_sqlite3_value_bytes(argv[0]);
- assert( zBlob==sqlcipher_sqlite3_value_blob(argv[0]) ); /* No encoding change */
- zText = (char *)contextMalloc(context, (2*(i64)nBlob)+4);
- if( zText ){
+ char const *zBlob = sqlcipher_sqlite3_value_blob(pValue);
+ int nBlob = sqlcipher_sqlite3_value_bytes(pValue);
+ assert( zBlob==sqlcipher_sqlite3_value_blob(pValue) ); /* No encoding change */
+ sqlcipher_sqlite3StrAccumEnlarge(pStr, nBlob*2 + 4);
+ if( pStr->accError==0 ){
+ char *zText = pStr->zText;
int i;
for(i=0; i<nBlob; i++){
zText[(i*2)+2] = hexdigits[(zBlob[i]>>4)&0x0F];
@@ -123359,43 +128704,49 @@ static void quoteFunc(sqlcipher_sqlite3_context *context, int argc, sqlcipher_sq
zText[(nBlob*2)+3] = '\0';
zText[0] = 'X';
zText[1] = '\'';
- sqlcipher_sqlite3_result_text(context, zText, -1, SQLITE_TRANSIENT);
- sqlcipher_sqlite3_free(zText);
+ pStr->nChar = nBlob*2 + 3;
}
break;
}
case SQLITE_TEXT: {
- int i,j;
- u64 n;
- const unsigned char *zArg = sqlcipher_sqlite3_value_text(argv[0]);
- char *z;
-
- if( zArg==0 ) return;
- for(i=0, n=0; zArg[i]; i++){ if( zArg[i]=='\'' ) n++; }
- z = contextMalloc(context, ((i64)i)+((i64)n)+3);
- if( z ){
- z[0] = '\'';
- for(i=0, j=1; zArg[i]; i++){
- z[j++] = zArg[i];
- if( zArg[i]=='\'' ){
- z[j++] = '\'';
- }
- }
- z[j++] = '\'';
- z[j] = 0;
- sqlcipher_sqlite3_result_text(context, z, j, sqlcipher_sqlite3_free);
- }
+ const unsigned char *zArg = sqlcipher_sqlite3_value_text(pValue);
+ sqlcipher_sqlite3_str_appendf(pStr, "%Q", zArg);
break;
}
default: {
- assert( sqlcipher_sqlite3_value_type(argv[0])==SQLITE_NULL );
- sqlcipher_sqlite3_result_text(context, "NULL", 4, SQLITE_STATIC);
+ assert( sqlcipher_sqlite3_value_type(pValue)==SQLITE_NULL );
+ sqlcipher_sqlite3_str_append(pStr, "NULL", 4);
break;
}
}
}
/*
+** Implementation of the QUOTE() function.
+**
+** The quote(X) function returns the text of an SQL literal which is the
+** value of its argument suitable for inclusion into an SQL statement.
+** Strings are surrounded by single-quotes with escapes on interior quotes
+** as needed. BLOBs are encoded as hexadecimal literals. Strings with
+** embedded NUL characters cannot be represented as string literals in SQL
+** and hence the returned string literal is truncated prior to the first NUL.
+*/
+static void quoteFunc(sqlcipher_sqlite3_context *context, int argc, sqlcipher_sqlite3_value **argv){
+ sqlcipher_sqlite3_str str;
+ sqlcipher_sqlite3 *db = sqlcipher_sqlite3_context_db_handle(context);
+ assert( argc==1 );
+ UNUSED_PARAMETER(argc);
+ sqlcipher_sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]);
+ sqlcipher_sqlite3QuoteValue(&str,argv[0]);
+ sqlcipher_sqlite3_result_text(context, sqlcipher_sqlite3StrAccumFinish(&str), str.nChar,
+ SQLITE_DYNAMIC);
+ if( str.accError!=SQLITE_OK ){
+ sqlcipher_sqlite3_result_null(context);
+ sqlcipher_sqlite3_result_error_code(context, str.accError);
+ }
+}
+
+/*
** The unicode() function. Return the integer unicode code-point value
** for the first character of the input string.
*/
@@ -123606,10 +128957,10 @@ static void trimFunc(
){
const unsigned char *zIn; /* Input string */
const unsigned char *zCharSet; /* Set of characters to trim */
- int nIn; /* Number of bytes in input */
+ unsigned int nIn; /* Number of bytes in input */
int flags; /* 1: trimleft 2: trimright 3: trim */
int i; /* Loop counter */
- unsigned char *aLen = 0; /* Length of each character in zCharSet */
+ unsigned int *aLen = 0; /* Length of each character in zCharSet */
unsigned char **azChar = 0; /* Individual characters in zCharSet */
int nChar; /* Number of characters in zCharSet */
@@ -123618,13 +128969,13 @@ static void trimFunc(
}
zIn = sqlcipher_sqlite3_value_text(argv[0]);
if( zIn==0 ) return;
- nIn = sqlcipher_sqlite3_value_bytes(argv[0]);
+ nIn = (unsigned)sqlcipher_sqlite3_value_bytes(argv[0]);
assert( zIn==sqlcipher_sqlite3_value_text(argv[0]) );
if( argc==1 ){
- static const unsigned char lenOne[] = { 1 };
+ static const unsigned lenOne[] = { 1 };
static unsigned char * const azOne[] = { (u8*)" " };
nChar = 1;
- aLen = (u8*)lenOne;
+ aLen = (unsigned*)lenOne;
azChar = (unsigned char **)azOne;
zCharSet = 0;
}else if( (zCharSet = sqlcipher_sqlite3_value_text(argv[1]))==0 ){
@@ -123635,15 +128986,16 @@ static void trimFunc(
SQLITE_SKIP_UTF8(z);
}
if( nChar>0 ){
- azChar = contextMalloc(context, ((i64)nChar)*(sizeof(char*)+1));
+ azChar = contextMalloc(context,
+ ((i64)nChar)*(sizeof(char*)+sizeof(unsigned)));
if( azChar==0 ){
return;
}
- aLen = (unsigned char*)&azChar[nChar];
+ aLen = (unsigned*)&azChar[nChar];
for(z=zCharSet, nChar=0; *z; nChar++){
azChar[nChar] = (unsigned char *)z;
SQLITE_SKIP_UTF8(z);
- aLen[nChar] = (u8)(z - azChar[nChar]);
+ aLen[nChar] = (unsigned)(z - azChar[nChar]);
}
}
}
@@ -123651,7 +129003,7 @@ static void trimFunc(
flags = SQLITE_PTR_TO_INT(sqlcipher_sqlite3_user_data(context));
if( flags & 1 ){
while( nIn>0 ){
- int len = 0;
+ unsigned int len = 0;
for(i=0; i<nChar; i++){
len = aLen[i];
if( len<=nIn && memcmp(zIn, azChar[i], len)==0 ) break;
@@ -123663,7 +129015,7 @@ static void trimFunc(
}
if( flags & 2 ){
while( nIn>0 ){
- int len = 0;
+ unsigned int len = 0;
for(i=0; i<nChar; i++){
len = aLen[i];
if( len<=nIn && memcmp(&zIn[nIn-len],azChar[i],len)==0 ) break;
@@ -124004,97 +129356,167 @@ static void minMaxFinalize(sqlcipher_sqlite3_context *context){
/*
** group_concat(EXPR, ?SEPARATOR?)
+**
+** The SEPARATOR goes before the EXPR string. This is tragic. The
+** groupConcatInverse() implementation would have been easier if the
+** SEPARATOR were appended after EXPR. And the order is undocumented,
+** so we could change it, in theory. But the old behavior has been
+** around for so long that we dare not, for fear of breaking something.
*/
+typedef struct {
+ StrAccum str; /* The accumulated concatenation */
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ int nAccum; /* Number of strings presently concatenated */
+ int nFirstSepLength; /* Used to detect separator length change */
+ /* If pnSepLengths!=0, refs an array of inter-string separator lengths,
+ ** stored as actually incorporated into presently accumulated result.
+ ** (Hence, its slots in use number nAccum-1 between method calls.)
+ ** If pnSepLengths==0, nFirstSepLength is the length used throughout.
+ */
+ int *pnSepLengths;
+#endif
+} GroupConcatCtx;
+
static void groupConcatStep(
sqlcipher_sqlite3_context *context,
int argc,
sqlcipher_sqlite3_value **argv
){
const char *zVal;
- StrAccum *pAccum;
+ GroupConcatCtx *pGCC;
const char *zSep;
int nVal, nSep;
assert( argc==1 || argc==2 );
if( sqlcipher_sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
- pAccum = (StrAccum*)sqlcipher_sqlite3_aggregate_context(context, sizeof(*pAccum));
-
- if( pAccum ){
+ pGCC = (GroupConcatCtx*)sqlcipher_sqlite3_aggregate_context(context, sizeof(*pGCC));
+ if( pGCC ){
sqlcipher_sqlite3 *db = sqlcipher_sqlite3_context_db_handle(context);
- int firstTerm = pAccum->mxAlloc==0;
- pAccum->mxAlloc = db->aLimit[SQLITE_LIMIT_LENGTH];
- if( !firstTerm ){
- if( argc==2 ){
- zSep = (char*)sqlcipher_sqlite3_value_text(argv[1]);
- nSep = sqlcipher_sqlite3_value_bytes(argv[1]);
- }else{
- zSep = ",";
- nSep = 1;
+ int firstTerm = pGCC->str.mxAlloc==0;
+ pGCC->str.mxAlloc = db->aLimit[SQLITE_LIMIT_LENGTH];
+ if( argc==1 ){
+ if( !firstTerm ){
+ sqlcipher_sqlite3_str_appendchar(&pGCC->str, 1, ',');
+ }
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ else{
+ pGCC->nFirstSepLength = 1;
}
- if( zSep ) sqlcipher_sqlite3_str_append(pAccum, zSep, nSep);
+#endif
+ }else if( !firstTerm ){
+ zSep = (char*)sqlcipher_sqlite3_value_text(argv[1]);
+ nSep = sqlcipher_sqlite3_value_bytes(argv[1]);
+ if( zSep ){
+ sqlcipher_sqlite3_str_append(&pGCC->str, zSep, nSep);
+ }
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ else{
+ nSep = 0;
+ }
+ if( nSep != pGCC->nFirstSepLength || pGCC->pnSepLengths != 0 ){
+ int *pnsl = pGCC->pnSepLengths;
+ if( pnsl == 0 ){
+ /* First separator length variation seen, start tracking them. */
+ pnsl = (int*)sqlcipher_sqlite3_malloc64((pGCC->nAccum+1) * sizeof(int));
+ if( pnsl!=0 ){
+ int i = 0, nA = pGCC->nAccum-1;
+ while( i<nA ) pnsl[i++] = pGCC->nFirstSepLength;
+ }
+ }else{
+ pnsl = (int*)sqlcipher_sqlite3_realloc64(pnsl, pGCC->nAccum * sizeof(int));
+ }
+ if( pnsl!=0 ){
+ if( ALWAYS(pGCC->nAccum>0) ){
+ pnsl[pGCC->nAccum-1] = nSep;
+ }
+ pGCC->pnSepLengths = pnsl;
+ }else{
+ sqlcipher_sqlite3StrAccumSetError(&pGCC->str, SQLITE_NOMEM);
+ }
+ }
+#endif
}
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ else{
+ pGCC->nFirstSepLength = sqlcipher_sqlite3_value_bytes(argv[1]);
+ }
+ pGCC->nAccum += 1;
+#endif
zVal = (char*)sqlcipher_sqlite3_value_text(argv[0]);
nVal = sqlcipher_sqlite3_value_bytes(argv[0]);
- if( zVal ) sqlcipher_sqlite3_str_append(pAccum, zVal, nVal);
+ if( zVal ) sqlcipher_sqlite3_str_append(&pGCC->str, zVal, nVal);
}
}
+
#ifndef SQLITE_OMIT_WINDOWFUNC
static void groupConcatInverse(
sqlcipher_sqlite3_context *context,
int argc,
sqlcipher_sqlite3_value **argv
){
- int n;
- StrAccum *pAccum;
+ GroupConcatCtx *pGCC;
assert( argc==1 || argc==2 );
+ (void)argc; /* Suppress unused parameter warning */
if( sqlcipher_sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
- pAccum = (StrAccum*)sqlcipher_sqlite3_aggregate_context(context, sizeof(*pAccum));
- /* pAccum is always non-NULL since groupConcatStep() will have always
+ pGCC = (GroupConcatCtx*)sqlcipher_sqlite3_aggregate_context(context, sizeof(*pGCC));
+ /* pGCC is always non-NULL since groupConcatStep() will have always
** run frist to initialize it */
- if( ALWAYS(pAccum) ){
- n = sqlcipher_sqlite3_value_bytes(argv[0]);
- if( argc==2 ){
- n += sqlcipher_sqlite3_value_bytes(argv[1]);
+ if( ALWAYS(pGCC) ){
+ int nVS;
+ /* Must call sqlcipher_sqlite3_value_text() to convert the argument into text prior
+ ** to invoking sqlcipher_sqlite3_value_bytes(), in case the text encoding is UTF16 */
+ (void)sqlcipher_sqlite3_value_text(argv[0]);
+ nVS = sqlcipher_sqlite3_value_bytes(argv[0]);
+ pGCC->nAccum -= 1;
+ if( pGCC->pnSepLengths!=0 ){
+ assert(pGCC->nAccum >= 0);
+ if( pGCC->nAccum>0 ){
+ nVS += *pGCC->pnSepLengths;
+ memmove(pGCC->pnSepLengths, pGCC->pnSepLengths+1,
+ (pGCC->nAccum-1)*sizeof(int));
+ }
}else{
- n++;
+ /* If removing single accumulated string, harmlessly over-do. */
+ nVS += pGCC->nFirstSepLength;
}
- if( n>=(int)pAccum->nChar ){
- pAccum->nChar = 0;
+ if( nVS>=(int)pGCC->str.nChar ){
+ pGCC->str.nChar = 0;
}else{
- pAccum->nChar -= n;
- memmove(pAccum->zText, &pAccum->zText[n], pAccum->nChar);
+ pGCC->str.nChar -= nVS;
+ memmove(pGCC->str.zText, &pGCC->str.zText[nVS], pGCC->str.nChar);
+ }
+ if( pGCC->str.nChar==0 ){
+ pGCC->str.mxAlloc = 0;
+ sqlcipher_sqlite3_free(pGCC->pnSepLengths);
+ pGCC->pnSepLengths = 0;
}
- if( pAccum->nChar==0 ) pAccum->mxAlloc = 0;
}
}
#else
# define groupConcatInverse 0
#endif /* SQLITE_OMIT_WINDOWFUNC */
static void groupConcatFinalize(sqlcipher_sqlite3_context *context){
- StrAccum *pAccum;
- pAccum = sqlcipher_sqlite3_aggregate_context(context, 0);
- if( pAccum ){
- if( pAccum->accError==SQLITE_TOOBIG ){
- sqlcipher_sqlite3_result_error_toobig(context);
- }else if( pAccum->accError==SQLITE_NOMEM ){
- sqlcipher_sqlite3_result_error_nomem(context);
- }else{
- sqlcipher_sqlite3_result_text(context, sqlcipher_sqlite3StrAccumFinish(pAccum), -1,
- sqlcipher_sqlite3_free);
- }
+ GroupConcatCtx *pGCC
+ = (GroupConcatCtx*)sqlcipher_sqlite3_aggregate_context(context, 0);
+ if( pGCC ){
+ sqlcipher_sqlite3ResultStrAccum(context, &pGCC->str);
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ sqlcipher_sqlite3_free(pGCC->pnSepLengths);
+#endif
}
}
#ifndef SQLITE_OMIT_WINDOWFUNC
static void groupConcatValue(sqlcipher_sqlite3_context *context){
- sqlcipher_sqlite3_str *pAccum;
- pAccum = (sqlcipher_sqlite3_str*)sqlcipher_sqlite3_aggregate_context(context, 0);
- if( pAccum ){
+ GroupConcatCtx *pGCC
+ = (GroupConcatCtx*)sqlcipher_sqlite3_aggregate_context(context, 0);
+ if( pGCC ){
+ StrAccum *pAccum = &pGCC->str;
if( pAccum->accError==SQLITE_TOOBIG ){
sqlcipher_sqlite3_result_error_toobig(context);
}else if( pAccum->accError==SQLITE_NOMEM ){
sqlcipher_sqlite3_result_error_nomem(context);
}else{
const char *zText = sqlcipher_sqlite3_str_value(pAccum);
- sqlcipher_sqlite3_result_text(context, zText, -1, SQLITE_TRANSIENT);
+ sqlcipher_sqlite3_result_text(context, zText, pAccum->nChar, SQLITE_TRANSIENT);
}
}
}
@@ -124167,11 +129589,14 @@ SQLITE_PRIVATE void sqlcipher_sqlite3RegisterLikeFunctions(sqlcipher_sqlite3 *db
SQLITE_PRIVATE int sqlcipher_sqlite3IsLikeFunction(sqlcipher_sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
FuncDef *pDef;
int nExpr;
- if( pExpr->op!=TK_FUNCTION || !pExpr->x.pList ){
+ assert( pExpr!=0 );
+ assert( pExpr->op==TK_FUNCTION );
+ assert( ExprUseXList(pExpr) );
+ if( !pExpr->x.pList ){
return 0;
}
- assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
nExpr = pExpr->x.pList->nExpr;
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
pDef = sqlcipher_sqlite3FindFunction(db, pExpr->u.zToken, nExpr, SQLITE_UTF8, 0);
#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
if( pDef==0 ) return 0;
@@ -124195,6 +129620,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3IsLikeFunction(sqlcipher_sqlite3 *db, Expr *
Expr *pEscape = pExpr->x.pList->a[2].pExpr;
char *zEscape;
if( pEscape->op!=TK_STRING ) return 0;
+ assert( !ExprHasProperty(pEscape, EP_IntValue) );
zEscape = pEscape->u.zToken;
if( zEscape[0]==0 || zEscape[1]!=0 ) return 0;
if( zEscape[0]==aWc[0] ) return 0;
@@ -124206,6 +129632,201 @@ SQLITE_PRIVATE int sqlcipher_sqlite3IsLikeFunction(sqlcipher_sqlite3 *db, Expr *
return 1;
}
+/* Mathematical Constants */
+#ifndef M_PI
+# define M_PI 3.141592653589793238462643383279502884
+#endif
+#ifndef M_LN10
+# define M_LN10 2.302585092994045684017991454684364208
+#endif
+#ifndef M_LN2
+# define M_LN2 0.693147180559945309417232121458176568
+#endif
+
+
+/* Extra math functions that require linking with -lm
+*/
+#ifdef SQLITE_ENABLE_MATH_FUNCTIONS
+/*
+** Implementation SQL functions:
+**
+** ceil(X)
+** ceiling(X)
+** floor(X)
+**
+** The sqlcipher_sqlite3_user_data() pointer is a pointer to the libm implementation
+** of the underlying C function.
+*/
+static void ceilingFunc(
+ sqlcipher_sqlite3_context *context,
+ int argc,
+ sqlcipher_sqlite3_value **argv
+){
+ assert( argc==1 );
+ switch( sqlcipher_sqlite3_value_numeric_type(argv[0]) ){
+ case SQLITE_INTEGER: {
+ sqlcipher_sqlite3_result_int64(context, sqlcipher_sqlite3_value_int64(argv[0]));
+ break;
+ }
+ case SQLITE_FLOAT: {
+ double (*x)(double) = (double(*)(double))sqlcipher_sqlite3_user_data(context);
+ sqlcipher_sqlite3_result_double(context, x(sqlcipher_sqlite3_value_double(argv[0])));
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+}
+
+/*
+** On some systems, ceil() and floor() are intrinsic function. You are
+** unable to take a pointer to these functions. Hence, we here wrap them
+** in our own actual functions.
+*/
+static double xCeil(double x){ return ceil(x); }
+static double xFloor(double x){ return floor(x); }
+
+/*
+** Implementation of SQL functions:
+**
+** ln(X) - natural logarithm
+** log(X) - log X base 10
+** log10(X) - log X base 10
+** log(B,X) - log X base B
+*/
+static void logFunc(
+ sqlcipher_sqlite3_context *context,
+ int argc,
+ sqlcipher_sqlite3_value **argv
+){
+ double x, b, ans;
+ assert( argc==1 || argc==2 );
+ switch( sqlcipher_sqlite3_value_numeric_type(argv[0]) ){
+ case SQLITE_INTEGER:
+ case SQLITE_FLOAT:
+ x = sqlcipher_sqlite3_value_double(argv[0]);
+ if( x<=0.0 ) return;
+ break;
+ default:
+ return;
+ }
+ if( argc==2 ){
+ switch( sqlcipher_sqlite3_value_numeric_type(argv[0]) ){
+ case SQLITE_INTEGER:
+ case SQLITE_FLOAT:
+ b = log(x);
+ if( b<=0.0 ) return;
+ x = sqlcipher_sqlite3_value_double(argv[1]);
+ if( x<=0.0 ) return;
+ break;
+ default:
+ return;
+ }
+ ans = log(x)/b;
+ }else{
+ ans = log(x);
+ switch( SQLITE_PTR_TO_INT(sqlcipher_sqlite3_user_data(context)) ){
+ case 1:
+ /* Convert from natural logarithm to log base 10 */
+ ans /= M_LN10;
+ break;
+ case 2:
+ /* Convert from natural logarithm to log base 2 */
+ ans /= M_LN2;
+ break;
+ default:
+ break;
+ }
+ }
+ sqlcipher_sqlite3_result_double(context, ans);
+}
+
+/*
+** Functions to converts degrees to radians and radians to degrees.
+*/
+static double degToRad(double x){ return x*(M_PI/180.0); }
+static double radToDeg(double x){ return x*(180.0/M_PI); }
+
+/*
+** Implementation of 1-argument SQL math functions:
+**
+** exp(X) - Compute e to the X-th power
+*/
+static void math1Func(
+ sqlcipher_sqlite3_context *context,
+ int argc,
+ sqlcipher_sqlite3_value **argv
+){
+ int type0;
+ double v0, ans;
+ double (*x)(double);
+ assert( argc==1 );
+ type0 = sqlcipher_sqlite3_value_numeric_type(argv[0]);
+ if( type0!=SQLITE_INTEGER && type0!=SQLITE_FLOAT ) return;
+ v0 = sqlcipher_sqlite3_value_double(argv[0]);
+ x = (double(*)(double))sqlcipher_sqlite3_user_data(context);
+ ans = x(v0);
+ sqlcipher_sqlite3_result_double(context, ans);
+}
+
+/*
+** Implementation of 2-argument SQL math functions:
+**
+** power(X,Y) - Compute X to the Y-th power
+*/
+static void math2Func(
+ sqlcipher_sqlite3_context *context,
+ int argc,
+ sqlcipher_sqlite3_value **argv
+){
+ int type0, type1;
+ double v0, v1, ans;
+ double (*x)(double,double);
+ assert( argc==2 );
+ type0 = sqlcipher_sqlite3_value_numeric_type(argv[0]);
+ if( type0!=SQLITE_INTEGER && type0!=SQLITE_FLOAT ) return;
+ type1 = sqlcipher_sqlite3_value_numeric_type(argv[1]);
+ if( type1!=SQLITE_INTEGER && type1!=SQLITE_FLOAT ) return;
+ v0 = sqlcipher_sqlite3_value_double(argv[0]);
+ v1 = sqlcipher_sqlite3_value_double(argv[1]);
+ x = (double(*)(double,double))sqlcipher_sqlite3_user_data(context);
+ ans = x(v0, v1);
+ sqlcipher_sqlite3_result_double(context, ans);
+}
+
+/*
+** Implementation of 0-argument pi() function.
+*/
+static void piFunc(
+ sqlcipher_sqlite3_context *context,
+ int argc,
+ sqlcipher_sqlite3_value **argv
+){
+ assert( argc==0 );
+ sqlcipher_sqlite3_result_double(context, M_PI);
+}
+
+#endif /* SQLITE_ENABLE_MATH_FUNCTIONS */
+
+/*
+** Implementation of sign(X) function.
+*/
+static void signFunc(
+ sqlcipher_sqlite3_context *context,
+ int argc,
+ sqlcipher_sqlite3_value **argv
+){
+ int type0;
+ double x;
+ UNUSED_PARAMETER(argc);
+ assert( argc==1 );
+ type0 = sqlcipher_sqlite3_value_numeric_type(argv[0]);
+ if( type0!=SQLITE_INTEGER && type0!=SQLITE_FLOAT ) return;
+ x = sqlcipher_sqlite3_value_double(argv[0]);
+ sqlcipher_sqlite3_result_int(context, x<0.0 ? -1 : x>0.0 ? +1 : 0);
+}
+
/*
** All of the FuncDef structures in the aBuiltinFunc[] array above
** to the global function hash table. This occurs at start-time (as
@@ -124226,12 +129847,12 @@ SQLITE_PRIVATE void sqlcipher_sqlite3RegisterBuiltinFunctions(void){
*/
static FuncDef aBuiltinFunc[] = {
/***** Functions only available with SQLITE_TESTCTRL_INTERNAL_FUNCTIONS *****/
+#if !defined(SQLITE_UNTESTABLE)
TEST_FUNC(implies_nonnull_row, 2, INLINEFUNC_implies_nonnull_row, 0),
TEST_FUNC(expr_compare, 2, INLINEFUNC_expr_compare, 0),
TEST_FUNC(expr_implies_expr, 2, INLINEFUNC_expr_implies_expr, 0),
-#ifdef SQLITE_DEBUG
- TEST_FUNC(affinity, 1, INLINEFUNC_affinity, 0),
-#endif
+ TEST_FUNC(affinity, 1, INLINEFUNC_affinity, 0),
+#endif /* !defined(SQLITE_UNTESTABLE) */
/***** Regular functions *****/
#ifdef SQLITE_SOUNDEX
FUNCTION(soundex, 1, 0, 0, soundexFunc ),
@@ -124251,8 +129872,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3RegisterBuiltinFunctions(void){
INLINE_FUNC(likelihood, 2, INLINEFUNC_unlikely, SQLITE_FUNC_UNLIKELY),
INLINE_FUNC(likely, 1, INLINEFUNC_unlikely, SQLITE_FUNC_UNLIKELY),
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
- FUNCTION2(sqlite_offset, 1, 0, 0, noopFunc, SQLITE_FUNC_OFFSET|
- SQLITE_FUNC_TYPEOF),
+ INLINE_FUNC(sqlite_offset, 1, INLINEFUNC_sqlite_offset, 0 ),
#endif
FUNCTION(ltrim, 1, 1, 0, trimFunc ),
FUNCTION(ltrim, 2, 1, 0, trimFunc ),
@@ -124263,15 +129883,17 @@ SQLITE_PRIVATE void sqlcipher_sqlite3RegisterBuiltinFunctions(void){
FUNCTION(min, -1, 0, 1, minmaxFunc ),
FUNCTION(min, 0, 0, 1, 0 ),
WAGGREGATE(min, 1, 0, 1, minmaxStep, minMaxFinalize, minMaxValue, 0,
- SQLITE_FUNC_MINMAX ),
+ SQLITE_FUNC_MINMAX|SQLITE_FUNC_ANYORDER ),
FUNCTION(max, -1, 1, 1, minmaxFunc ),
FUNCTION(max, 0, 1, 1, 0 ),
WAGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize, minMaxValue, 0,
- SQLITE_FUNC_MINMAX ),
+ SQLITE_FUNC_MINMAX|SQLITE_FUNC_ANYORDER ),
FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF),
+ FUNCTION2(subtype, 1, 0, 0, subtypeFunc, SQLITE_FUNC_TYPEOF),
FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH),
FUNCTION(instr, 2, 0, 0, instrFunc ),
FUNCTION(printf, -1, 0, 0, printfFunc ),
+ FUNCTION(format, -1, 0, 0, printfFunc ),
FUNCTION(unicode, 1, 0, 0, unicodeFunc ),
FUNCTION(char, -1, 0, 0, charFunc ),
FUNCTION(abs, 1, 0, 0, absFunc ),
@@ -124303,9 +129925,10 @@ SQLITE_PRIVATE void sqlcipher_sqlite3RegisterBuiltinFunctions(void){
WAGGREGATE(total, 1,0,0, sumStep,totalFinalize,totalFinalize,sumInverse, 0),
WAGGREGATE(avg, 1,0,0, sumStep, avgFinalize, avgFinalize, sumInverse, 0),
WAGGREGATE(count, 0,0,0, countStep,
- countFinalize, countFinalize, countInverse, SQLITE_FUNC_COUNT ),
+ countFinalize, countFinalize, countInverse,
+ SQLITE_FUNC_COUNT|SQLITE_FUNC_ANYORDER ),
WAGGREGATE(count, 1,0,0, countStep,
- countFinalize, countFinalize, countInverse, 0 ),
+ countFinalize, countFinalize, countInverse, SQLITE_FUNC_ANYORDER ),
WAGGREGATE(group_concat, 1, 0, 0, groupConcatStep,
groupConcatFinalize, groupConcatValue, groupConcatInverse, 0),
WAGGREGATE(group_concat, 2, 0, 0, groupConcatStep,
@@ -124324,6 +129947,43 @@ SQLITE_PRIVATE void sqlcipher_sqlite3RegisterBuiltinFunctions(void){
#endif
FUNCTION(coalesce, 1, 0, 0, 0 ),
FUNCTION(coalesce, 0, 0, 0, 0 ),
+#ifdef SQLITE_ENABLE_MATH_FUNCTIONS
+ MFUNCTION(ceil, 1, xCeil, ceilingFunc ),
+ MFUNCTION(ceiling, 1, xCeil, ceilingFunc ),
+ MFUNCTION(floor, 1, xFloor, ceilingFunc ),
+#if SQLITE_HAVE_C99_MATH_FUNCS
+ MFUNCTION(trunc, 1, trunc, ceilingFunc ),
+#endif
+ FUNCTION(ln, 1, 0, 0, logFunc ),
+ FUNCTION(log, 1, 1, 0, logFunc ),
+ FUNCTION(log10, 1, 1, 0, logFunc ),
+ FUNCTION(log2, 1, 2, 0, logFunc ),
+ FUNCTION(log, 2, 0, 0, logFunc ),
+ MFUNCTION(exp, 1, exp, math1Func ),
+ MFUNCTION(pow, 2, pow, math2Func ),
+ MFUNCTION(power, 2, pow, math2Func ),
+ MFUNCTION(mod, 2, fmod, math2Func ),
+ MFUNCTION(acos, 1, acos, math1Func ),
+ MFUNCTION(asin, 1, asin, math1Func ),
+ MFUNCTION(atan, 1, atan, math1Func ),
+ MFUNCTION(atan2, 2, atan2, math2Func ),
+ MFUNCTION(cos, 1, cos, math1Func ),
+ MFUNCTION(sin, 1, sin, math1Func ),
+ MFUNCTION(tan, 1, tan, math1Func ),
+ MFUNCTION(cosh, 1, cosh, math1Func ),
+ MFUNCTION(sinh, 1, sinh, math1Func ),
+ MFUNCTION(tanh, 1, tanh, math1Func ),
+#if SQLITE_HAVE_C99_MATH_FUNCS
+ MFUNCTION(acosh, 1, acosh, math1Func ),
+ MFUNCTION(asinh, 1, asinh, math1Func ),
+ MFUNCTION(atanh, 1, atanh, math1Func ),
+#endif
+ MFUNCTION(sqrt, 1, sqrt, math1Func ),
+ MFUNCTION(radians, 1, degToRad, math1Func ),
+ MFUNCTION(degrees, 1, radToDeg, math1Func ),
+ FUNCTION(pi, 0, 0, 0, piFunc ),
+#endif /* SQLITE_ENABLE_MATH_FUNCTIONS */
+ FUNCTION(sign, 1, 0, 0, signFunc ),
INLINE_FUNC(coalesce, -1, INLINEFUNC_coalesce, 0 ),
INLINE_FUNC(iif, 3, INLINEFUNC_iif, 0 ),
};
@@ -124332,6 +129992,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3RegisterBuiltinFunctions(void){
#endif
sqlcipher_sqlite3WindowFunctions();
sqlcipher_sqlite3RegisterDateTimeFunctions();
+ sqlcipher_sqlite3RegisterJsonFunctions();
sqlcipher_sqlite3InsertBuiltinFuncs(aBuiltinFunc, ArraySize(aBuiltinFunc));
#if 0 /* Enable to print out how the built-in functions are hashed */
@@ -124343,6 +130004,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3RegisterBuiltinFunctions(void){
for(p=sqlcipher_sqlite3BuiltinFunctions.a[i]; p; p=p->u.pHash){
int n = sqlcipher_sqlite3Strlen30(p->zName);
int h = p->zName[0] + n;
+ assert( p->funcFlags & SQLITE_FUNC_BUILTIN );
printf(" %s(%d)", p->zName, h);
}
printf("\n");
@@ -124570,7 +130232,9 @@ SQLITE_PRIVATE int sqlcipher_sqlite3FkLocateIndex(
*/
if( pParent->iPKey>=0 ){
if( !zKey ) return 0;
- if( !sqlcipher_sqlite3StrICmp(pParent->aCol[pParent->iPKey].zName, zKey) ) return 0;
+ if( !sqlcipher_sqlite3StrICmp(pParent->aCol[pParent->iPKey].zCnName, zKey) ){
+ return 0;
+ }
}
}else if( paiCol ){
assert( nCol>1 );
@@ -124612,11 +130276,11 @@ SQLITE_PRIVATE int sqlcipher_sqlite3FkLocateIndex(
/* If the index uses a collation sequence that is different from
** the default collation sequence for the column, this index is
** unusable. Bail out early in this case. */
- zDfltColl = pParent->aCol[iCol].zColl;
+ zDfltColl = sqlcipher_sqlite3ColumnColl(&pParent->aCol[iCol]);
if( !zDfltColl ) zDfltColl = sqlcipher_sqlite3StrBINARY;
if( sqlcipher_sqlite3StrICmp(pIdx->azColl[i], zDfltColl) ) break;
- zIdxCol = pParent->aCol[iCol].zName;
+ zIdxCol = pParent->aCol[iCol].zCnName;
for(j=0; j<nCol; j++){
if( sqlcipher_sqlite3StrICmp(pFKey->aCol[j].zCol, zIdxCol)==0 ){
if( aiCol ) aiCol[i] = pFKey->aCol[j].iFrom;
@@ -124743,7 +130407,6 @@ static void fkLookupParent(
}else{
int nCol = pFKey->nCol;
int regTemp = sqlcipher_sqlite3GetTempRange(pParse, nCol);
- int regRec = sqlcipher_sqlite3GetTempReg(pParse);
sqlcipher_sqlite3VdbeAddOp3(v, OP_OpenRead, iCur, pIdx->tnum, iDb);
sqlcipher_sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
@@ -124783,11 +130446,10 @@ static void fkLookupParent(
sqlcipher_sqlite3VdbeGoto(v, iOk);
}
- sqlcipher_sqlite3VdbeAddOp4(v, OP_MakeRecord, regTemp, nCol, regRec,
+ sqlcipher_sqlite3VdbeAddOp4(v, OP_Affinity, regTemp, nCol, 0,
sqlcipher_sqlite3IndexAffinityStr(pParse->db,pIdx), nCol);
- sqlcipher_sqlite3VdbeAddOp4Int(v, OP_Found, iCur, iOk, regRec, 0); VdbeCoverage(v);
-
- sqlcipher_sqlite3ReleaseTempReg(pParse, regRec);
+ sqlcipher_sqlite3VdbeAddOp4Int(v, OP_Found, iCur, iOk, regTemp, nCol);
+ VdbeCoverage(v);
sqlcipher_sqlite3ReleaseTempRange(pParse, regTemp, nCol);
}
}
@@ -124840,7 +130502,7 @@ static Expr *exprTableRegister(
pCol = &pTab->aCol[iCol];
pExpr->iTable = regBase + sqlcipher_sqlite3TableColumnToStorage(pTab,iCol) + 1;
pExpr->affExpr = pCol->affinity;
- zColl = pCol->zColl;
+ zColl = sqlcipher_sqlite3ColumnColl(pCol);
if( zColl==0 ) zColl = db->pDfltColl->zName;
pExpr = sqlcipher_sqlite3ExprAddCollateString(pParse, pExpr, zColl);
}else{
@@ -124863,6 +130525,7 @@ static Expr *exprTableColumn(
){
Expr *pExpr = sqlcipher_sqlite3Expr(db, TK_COLUMN, 0);
if( pExpr ){
+ assert( ExprUseYTab(pExpr) );
pExpr->y.pTab = pTab;
pExpr->iTable = iCursor;
pExpr->iColumn = iCol;
@@ -124888,14 +130551,10 @@ static Expr *exprTableColumn(
** Operation | FK type | Action taken
** --------------------------------------------------------------------------
** DELETE immediate Increment the "immediate constraint counter".
-** Or, if the ON (UPDATE|DELETE) action is RESTRICT,
-** 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.
**
** INSERT deferred Decrement the "deferred constraint counter".
**
@@ -124949,7 +130608,7 @@ static void fkScanChildren(
pLeft = exprTableRegister(pParse, pTab, regData, iCol);
iCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom;
assert( iCol>=0 );
- zCol = pFKey->pFrom->aCol[iCol].zName;
+ zCol = pFKey->pFrom->aCol[iCol].zCnName;
pRight = sqlcipher_sqlite3Expr(db, TK_ID, zCol);
pEq = sqlcipher_sqlite3PExpr(pParse, TK_EQ, pLeft, pRight);
pWhere = sqlcipher_sqlite3ExprAnd(pParse, pWhere, pEq);
@@ -124984,7 +130643,7 @@ static void fkScanChildren(
i16 iCol = pIdx->aiColumn[i];
assert( iCol>=0 );
pLeft = exprTableRegister(pParse, pTab, regData, iCol);
- pRight = sqlcipher_sqlite3Expr(db, TK_ID, pTab->aCol[iCol].zName);
+ pRight = sqlcipher_sqlite3Expr(db, TK_ID, pTab->aCol[iCol].zCnName);
pEq = sqlcipher_sqlite3PExpr(pParse, TK_IS, pLeft, pRight);
pAll = sqlcipher_sqlite3ExprAnd(pParse, pAll, pEq);
}
@@ -125003,7 +130662,7 @@ static void fkScanChildren(
** clause. For each row found, increment either the deferred or immediate
** foreign key constraint counter. */
if( pParse->nErr==0 ){
- pWInfo = sqlcipher_sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0);
+ pWInfo = sqlcipher_sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0, 0);
sqlcipher_sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
if( pWInfo ){
sqlcipher_sqlite3WhereEnd(pWInfo);
@@ -125055,6 +130714,25 @@ static void fkTriggerDelete(sqlcipher_sqlite3 *dbMem, Trigger *p){
}
/*
+** Clear the apTrigger[] cache of CASCADE triggers for all foreign keys
+** in a particular database. This needs to happen when the schema
+** changes.
+*/
+SQLITE_PRIVATE void sqlcipher_sqlite3FkClearTriggerCache(sqlcipher_sqlite3 *db, int iDb){
+ HashElem *k;
+ Hash *pHash = &db->aDb[iDb].pSchema->tblHash;
+ for(k=sqliteHashFirst(pHash); k; k=sqliteHashNext(k)){
+ Table *pTab = sqliteHashData(k);
+ FKey *pFKey;
+ if( !IsOrdinaryTable(pTab) ) continue;
+ for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){
+ fkTriggerDelete(db, pFKey->apTrigger[0]); pFKey->apTrigger[0] = 0;
+ fkTriggerDelete(db, pFKey->apTrigger[1]); pFKey->apTrigger[1] = 0;
+ }
+ }
+}
+
+/*
** This function is called to generate code that runs when table pTab is
** being dropped from the database. The SrcList passed as the second argument
** to this function contains a single entry guaranteed to resolve to
@@ -125073,12 +130751,12 @@ static void fkTriggerDelete(sqlcipher_sqlite3 *dbMem, Trigger *p){
*/
SQLITE_PRIVATE void sqlcipher_sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTab){
sqlcipher_sqlite3 *db = pParse->db;
- if( (db->flags&SQLITE_ForeignKeys) && !IsVirtual(pTab) ){
+ if( (db->flags&SQLITE_ForeignKeys) && IsOrdinaryTable(pTab) ){
int iSkip = 0;
Vdbe *v = sqlcipher_sqlite3GetVdbe(pParse);
assert( v ); /* VDBE has already been allocated */
- assert( pTab->pSelect==0 ); /* Not a view */
+ assert( IsOrdinaryTable(pTab) );
if( sqlcipher_sqlite3FkReferences(pTab)==0 ){
/* Search for a deferred foreign key constraint for which this table
** is the child table. If one cannot be found, return without
@@ -125086,7 +130764,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3FkDropTable(Parse *pParse, SrcList *pName,
** the entire DELETE if there are no outstanding deferred constraints
** when this statement is run. */
FKey *p;
- for(p=pTab->pFKey; p; p=p->pNextFrom){
+ for(p=pTab->u.tab.pFKey; p; p=p->pNextFrom){
if( p->isDeferred || (db->flags & SQLITE_DeferFKs) ) break;
}
if( !p ) return;
@@ -125175,7 +130853,7 @@ static int fkParentIsModified(
if( aChange[iKey]>=0 || (iKey==pTab->iPKey && bChngRowid) ){
Column *pCol = &pTab->aCol[iKey];
if( zKey ){
- if( 0==sqlcipher_sqlite3StrICmp(pCol->zName, zKey) ) return 1;
+ if( 0==sqlcipher_sqlite3StrICmp(pCol->zCnName, zKey) ) return 1;
}else if( pCol->colFlags & COLFLAG_PRIMKEY ){
return 1;
}
@@ -125242,13 +130920,14 @@ SQLITE_PRIVATE void sqlcipher_sqlite3FkCheck(
/* If foreign-keys are disabled, this function is a no-op. */
if( (db->flags&SQLITE_ForeignKeys)==0 ) return;
+ if( !IsOrdinaryTable(pTab) ) return;
iDb = sqlcipher_sqlite3SchemaToIndex(db, pTab->pSchema);
zDb = db->aDb[iDb].zDbSName;
/* Loop through all the foreign key constraints for which pTab is the
** child table (the table that the foreign key definition is part of). */
- for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){
+ for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pFKey->pNextFrom){
Table *pTo; /* Parent table of foreign key pFKey */
Index *pIdx = 0; /* Index on key columns in pTo */
int *aiFree = 0;
@@ -125315,7 +130994,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3FkCheck(
** values read from the parent table are NULL. */
if( db->xAuth ){
int rcauth;
- char *zCol = pTo->aCol[pIdx ? pIdx->aiColumn[i] : pTo->iPKey].zName;
+ char *zCol = pTo->aCol[pIdx ? pIdx->aiColumn[i] : pTo->iPKey].zCnName;
rcauth = sqlcipher_sqlite3AuthReadCol(pParse, pTo->zName, zCol, iDb);
bIgnore = (rcauth==SQLITE_IGNORE);
}
@@ -125379,7 +131058,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3FkCheck(
** child table as a SrcList for sqlcipher_sqlite3WhereBegin() */
pSrc = sqlcipher_sqlite3SrcListAppend(pParse, 0, 0, 0);
if( pSrc ){
- struct SrcList_item *pItem = pSrc->a;
+ SrcItem *pItem = pSrc->a;
pItem->pTab = pFKey->pFrom;
pItem->zName = pFKey->pFrom->zName;
pItem->pTab->nTabRef++;
@@ -125430,10 +131109,10 @@ SQLITE_PRIVATE u32 sqlcipher_sqlite3FkOldmask(
Table *pTab /* Table being modified */
){
u32 mask = 0;
- if( pParse->db->flags&SQLITE_ForeignKeys ){
+ if( pParse->db->flags&SQLITE_ForeignKeys && IsOrdinaryTable(pTab) ){
FKey *p;
int i;
- for(p=pTab->pFKey; p; p=p->pNextFrom){
+ for(p=pTab->u.tab.pFKey; p; p=p->pNextFrom){
for(i=0; i<p->nCol; i++) mask |= COLUMN_MASK(p->aCol[i].iFrom);
}
for(p=sqlcipher_sqlite3FkReferences(pTab); p; p=p->pNextTo){
@@ -125467,7 +131146,9 @@ SQLITE_PRIVATE u32 sqlcipher_sqlite3FkOldmask(
**
** For an UPDATE, this function returns 2 if:
**
-** * There are any FKs for which pTab is the child and the parent table, or
+** * There are any FKs for which pTab is the child and the parent table
+** and any FK processing at all is required (even of a different FK), or
+**
** * the UPDATE modifies one or more parent keys for which the action is
** not "NO ACTION" (i.e. is CASCADE, SET DEFAULT or SET NULL).
**
@@ -125479,23 +131160,24 @@ SQLITE_PRIVATE int sqlcipher_sqlite3FkRequired(
int *aChange, /* Non-NULL for UPDATE operations */
int chngRowid /* True for UPDATE that affects rowid */
){
- int eRet = 0;
- if( pParse->db->flags&SQLITE_ForeignKeys ){
+ int eRet = 1; /* Value to return if bHaveFK is true */
+ int bHaveFK = 0; /* If FK processing is required */
+ if( pParse->db->flags&SQLITE_ForeignKeys && IsOrdinaryTable(pTab) ){
if( !aChange ){
/* A DELETE operation. Foreign key processing is required if the
** table in question is either the child or parent table for any
** foreign key constraint. */
- eRet = (sqlcipher_sqlite3FkReferences(pTab) || pTab->pFKey);
+ bHaveFK = (sqlcipher_sqlite3FkReferences(pTab) || pTab->u.tab.pFKey);
}else{
/* This is an UPDATE. Foreign key processing is only required if the
** operation modifies one or more child or parent key columns. */
FKey *p;
/* Check if any child key columns are being modified. */
- for(p=pTab->pFKey; p; p=p->pNextFrom){
- if( 0==sqlcipher_sqlite3_stricmp(pTab->zName, p->zTo) ) return 2;
+ for(p=pTab->u.tab.pFKey; p; p=p->pNextFrom){
if( fkChildIsModified(pTab, p, aChange, chngRowid) ){
- eRet = 1;
+ if( 0==sqlcipher_sqlite3_stricmp(pTab->zName, p->zTo) ) eRet = 2;
+ bHaveFK = 1;
}
}
@@ -125503,12 +131185,12 @@ SQLITE_PRIVATE int sqlcipher_sqlite3FkRequired(
for(p=sqlcipher_sqlite3FkReferences(pTab); p; p=p->pNextTo){
if( fkParentIsModified(pTab, p, aChange, chngRowid) ){
if( p->aAction[1]!=OE_None ) return 2;
- eRet = 1;
+ bHaveFK = 1;
}
}
}
}
- return eRet;
+ return bHaveFK ? eRet : 0;
}
/*
@@ -125520,9 +131202,9 @@ SQLITE_PRIVATE int sqlcipher_sqlite3FkRequired(
**
** It returns a pointer to a Trigger structure containing a trigger
** equivalent to the ON UPDATE or ON DELETE action specified by pFKey.
-** If the action is "NO ACTION" or "RESTRICT", then a NULL pointer is
-** returned (these actions require no special handling by the triggers
-** sub-system, code for them is created by fkScanChildren()).
+** If the action is "NO ACTION" then a NULL pointer is returned (these actions
+** require no special handling by the triggers sub-system, code for them is
+** created by fkScanChildren()).
**
** For example, if pFKey is the foreign key and pTab is table "p" in
** the following schema:
@@ -125585,8 +131267,8 @@ static Trigger *fkActionTrigger(
assert( pIdx!=0 || (pTab->iPKey>=0 && pTab->iPKey<pTab->nCol) );
assert( pIdx==0 || pIdx->aiColumn[i]>=0 );
sqlcipher_sqlite3TokenInit(&tToCol,
- pTab->aCol[pIdx ? pIdx->aiColumn[i] : pTab->iPKey].zName);
- sqlcipher_sqlite3TokenInit(&tFromCol, pFKey->pFrom->aCol[iFromCol].zName);
+ pTab->aCol[pIdx ? pIdx->aiColumn[i] : pTab->iPKey].zCnName);
+ sqlcipher_sqlite3TokenInit(&tFromCol, pFKey->pFrom->aCol[iFromCol].zCnName);
/* Create the expression "OLD.zToCol = zFromCol". It is important
** that the "OLD.zToCol" term is on the LHS of the = operator, so
@@ -125631,7 +131313,7 @@ static Trigger *fkActionTrigger(
testcase( pCol->colFlags & COLFLAG_STORED );
pDflt = 0;
}else{
- pDflt = pCol->pDflt;
+ pDflt = sqlcipher_sqlite3ColumnExpr(pFKey->pFrom, pCol);
}
if( pDflt ){
pNew = sqlcipher_sqlite3ExprDup(db, pDflt, 0);
@@ -125651,18 +131333,23 @@ static Trigger *fkActionTrigger(
nFrom = sqlcipher_sqlite3Strlen30(zFrom);
if( action==OE_Restrict ){
+ int iDb = sqlcipher_sqlite3SchemaToIndex(db, pTab->pSchema);
Token tFrom;
+ Token tDb;
Expr *pRaise;
tFrom.z = zFrom;
tFrom.n = nFrom;
+ tDb.z = db->aDb[iDb].zDbSName;
+ tDb.n = sqlcipher_sqlite3Strlen30(tDb.z);
+
pRaise = sqlcipher_sqlite3Expr(db, TK_RAISE, "FOREIGN KEY constraint failed");
if( pRaise ){
pRaise->affExpr = OE_Abort;
}
pSelect = sqlcipher_sqlite3SelectNew(pParse,
sqlcipher_sqlite3ExprListAppend(pParse, 0, pRaise),
- sqlcipher_sqlite3SrcListAppend(pParse, 0, &tFrom, 0),
+ sqlcipher_sqlite3SrcListAppend(pParse, 0, &tDb, &tFrom),
pWhere,
0, 0, 0, 0, 0
);
@@ -125768,9 +131455,9 @@ SQLITE_PRIVATE void sqlcipher_sqlite3FkDelete(sqlcipher_sqlite3 *db, Table *pTab
FKey *pFKey; /* Iterator variable */
FKey *pNext; /* Copy of pFKey->pNextFrom */
- assert( db==0 || IsVirtual(pTab)
- || sqlcipher_sqlite3SchemaMutexHeld(db, 0, pTab->pSchema) );
- for(pFKey=pTab->pFKey; pFKey; pFKey=pNext){
+ assert( IsOrdinaryTable(pTab) );
+ for(pFKey=pTab->u.tab.pFKey; pFKey; pFKey=pNext){
+ assert( db==0 || sqlcipher_sqlite3SchemaMutexHeld(db, 0, pTab->pSchema) );
/* Remove the FK from the fkeyHash hash table. */
if( !db || db->pnBytesFreed==0 ){
@@ -125850,7 +131537,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3OpenTable(
}else{
Index *pPk = sqlcipher_sqlite3PrimaryKeyIndex(pTab);
assert( pPk!=0 );
- assert( pPk->tnum==pTab->tnum );
+ assert( pPk->tnum==pTab->tnum || CORRUPT_DB );
sqlcipher_sqlite3VdbeAddOp3(v, opcode, iCur, pPk->tnum, iDb);
sqlcipher_sqlite3VdbeSetP4KeyInfo(pParse, pPk);
VdbeComment((v, "%s", pTab->zName));
@@ -125917,28 +131604,68 @@ SQLITE_PRIVATE const char *sqlcipher_sqlite3IndexAffinityStr(sqlcipher_sqlite3 *
}
/*
+** Make changes to the evolving bytecode to do affinity transformations
+** of values that are about to be gathered into a row for table pTab.
+**
+** For ordinary (legacy, non-strict) tables:
+** -----------------------------------------
+**
** Compute the affinity string for table pTab, if it has not already been
** computed. As an optimization, omit trailing SQLITE_AFF_BLOB affinities.
**
-** If the affinity exists (if it is no entirely SQLITE_AFF_BLOB 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,
+** If the affinity string is empty (because it was all SQLITE_AFF_BLOB entries
+** which were then optimized out) then this routine becomes a no-op.
+**
+** Otherwise if iReg>0 then code an OP_Affinity opcode that will set the
+** affinities for register iReg and following. Or if 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
-** ------------------------------
-** 'A' BLOB
-** 'B' TEXT
-** 'C' NUMERIC
-** 'D' INTEGER
-** 'E' REAL
+** Character Column affinity
+** --------- ---------------
+** 'A' BLOB
+** 'B' TEXT
+** 'C' NUMERIC
+** 'D' INTEGER
+** 'E' REAL
+**
+** For STRICT tables:
+** ------------------
+**
+** Generate an appropropriate OP_TypeCheck opcode that will verify the
+** datatypes against the column definitions in pTab. If iReg==0, that
+** means an OP_MakeRecord opcode has already been generated and should be
+** the last opcode generated. The new OP_TypeCheck needs to be inserted
+** before the OP_MakeRecord. The new OP_TypeCheck should use the same
+** register set as the OP_MakeRecord. If iReg>0 then register iReg is
+** the first of a series of registers that will form the new record.
+** Apply the type checking to that array of registers.
*/
SQLITE_PRIVATE void sqlcipher_sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){
int i, j;
- char *zColAff = pTab->zColAff;
+ char *zColAff;
+ if( pTab->tabFlags & TF_Strict ){
+ if( iReg==0 ){
+ /* Move the previous opcode (which should be OP_MakeRecord) forward
+ ** by one slot and insert a new OP_TypeCheck where the current
+ ** OP_MakeRecord is found */
+ VdbeOp *pPrev;
+ sqlcipher_sqlite3VdbeAppendP4(v, pTab, P4_TABLE);
+ pPrev = sqlcipher_sqlite3VdbeGetOp(v, -1);
+ assert( pPrev!=0 );
+ assert( pPrev->opcode==OP_MakeRecord || sqlcipher_sqlite3VdbeDb(v)->mallocFailed );
+ pPrev->opcode = OP_TypeCheck;
+ sqlcipher_sqlite3VdbeAddOp3(v, OP_MakeRecord, pPrev->p1, pPrev->p2, pPrev->p3);
+ }else{
+ /* Insert an isolated OP_Typecheck */
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_TypeCheck, iReg, pTab->nNVCol);
+ sqlcipher_sqlite3VdbeAppendP4(v, pTab, P4_TABLE);
+ }
+ return;
+ }
+ zColAff = pTab->zColAff;
if( zColAff==0 ){
sqlcipher_sqlite3 *db = sqlcipher_sqlite3VdbeDb(v);
zColAff = (char *)sqlcipher_sqlite3DbMallocRaw(0, pTab->nCol+1);
@@ -125948,7 +131675,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3TableAffinity(Vdbe *v, Table *pTab, int iRe
}
for(i=j=0; i<pTab->nCol; i++){
- assert( pTab->aCol[i].affinity!=0 );
+ assert( pTab->aCol[i].affinity!=0 || sqlcipher_sqlite3VdbeParser(v)->nErr>0 );
if( (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 ){
zColAff[j++] = pTab->aCol[i].affinity;
}
@@ -125964,6 +131691,8 @@ SQLITE_PRIVATE void sqlcipher_sqlite3TableAffinity(Vdbe *v, Table *pTab, int iRe
if( iReg ){
sqlcipher_sqlite3VdbeAddOp4(v, OP_Affinity, iReg, i, 0, zColAff, i);
}else{
+ assert( sqlcipher_sqlite3VdbeGetOp(v, -1)->opcode==OP_MakeRecord
+ || sqlcipher_sqlite3VdbeDb(v)->mallocFailed );
sqlcipher_sqlite3VdbeChangeP4(v, -1, zColAff, i);
}
}
@@ -126047,24 +131776,30 @@ SQLITE_PRIVATE void sqlcipher_sqlite3ComputeGeneratedColumns(
** that appropriate affinity has been applied to the regular columns
*/
sqlcipher_sqlite3TableAffinity(pParse->pVdbe, pTab, iRegStore);
- if( (pTab->tabFlags & TF_HasStored)!=0
- && (pOp = sqlcipher_sqlite3VdbeGetOp(pParse->pVdbe,-1))->opcode==OP_Affinity
- ){
- /* Change the OP_Affinity argument to '@' (NONE) for all stored
- ** columns. '@' is the no-op affinity and those columns have not
- ** yet been computed. */
- int ii, jj;
- char *zP4 = pOp->p4.z;
- assert( zP4!=0 );
- assert( pOp->p4type==P4_DYNAMIC );
- for(ii=jj=0; zP4[jj]; ii++){
- if( pTab->aCol[ii].colFlags & COLFLAG_VIRTUAL ){
- continue;
- }
- if( pTab->aCol[ii].colFlags & COLFLAG_STORED ){
- zP4[jj] = SQLITE_AFF_NONE;
+ if( (pTab->tabFlags & TF_HasStored)!=0 ){
+ pOp = sqlcipher_sqlite3VdbeGetOp(pParse->pVdbe,-1);
+ if( pOp->opcode==OP_Affinity ){
+ /* Change the OP_Affinity argument to '@' (NONE) for all stored
+ ** columns. '@' is the no-op affinity and those columns have not
+ ** yet been computed. */
+ int ii, jj;
+ char *zP4 = pOp->p4.z;
+ assert( zP4!=0 );
+ assert( pOp->p4type==P4_DYNAMIC );
+ for(ii=jj=0; zP4[jj]; ii++){
+ if( pTab->aCol[ii].colFlags & COLFLAG_VIRTUAL ){
+ continue;
+ }
+ if( pTab->aCol[ii].colFlags & COLFLAG_STORED ){
+ zP4[jj] = SQLITE_AFF_NONE;
+ }
+ jj++;
}
- jj++;
+ }else if( pOp->opcode==OP_TypeCheck ){
+ /* If an OP_TypeCheck was generated because the table is STRICT,
+ ** then set the P3 operand to indicate that generated columns should
+ ** not be checked */
+ pOp->p3 = 1;
}
}
@@ -126100,7 +131835,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3ComputeGeneratedColumns(
int x;
pCol->colFlags |= COLFLAG_BUSY;
w.eCode = 0;
- sqlcipher_sqlite3WalkExpr(&w, pCol->pDflt);
+ sqlcipher_sqlite3WalkExpr(&w, sqlcipher_sqlite3ColumnExpr(pTab, pCol));
pCol->colFlags &= ~COLFLAG_BUSY;
if( w.eCode & COLFLAG_NOTAVAIL ){
pRedo = pCol;
@@ -126109,13 +131844,13 @@ SQLITE_PRIVATE void sqlcipher_sqlite3ComputeGeneratedColumns(
eProgress = 1;
assert( pCol->colFlags & COLFLAG_GENERATED );
x = sqlcipher_sqlite3TableColumnToStorage(pTab, i) + iRegStore;
- sqlcipher_sqlite3ExprCodeGeneratedColumn(pParse, pCol, x);
+ sqlcipher_sqlite3ExprCodeGeneratedColumn(pParse, pTab, pCol, x);
pCol->colFlags &= ~COLFLAG_NOTAVAIL;
}
}
}while( pRedo && eProgress );
if( pRedo ){
- sqlcipher_sqlite3ErrorMsg(pParse, "generated column loop on \"%s\"", pRedo->zName);
+ sqlcipher_sqlite3ErrorMsg(pParse, "generated column loop on \"%s\"", pRedo->zCnName);
}
pParse->iSelfTab = 0;
}
@@ -126165,7 +131900,7 @@ static int autoIncBegin(
** Ticket d8dc2b3a58cd5dc2918a1d4acb 2018-05-23 */
if( pSeqTab==0
|| !HasRowid(pSeqTab)
- || IsVirtual(pSeqTab)
+ || NEVER(IsVirtual(pSeqTab))
|| pSeqTab->nCol!=2
){
pParse->nErr++;
@@ -126177,7 +131912,9 @@ static int autoIncBegin(
while( pInfo && pInfo->pTab!=pTab ){ pInfo = pInfo->pNext; }
if( pInfo==0 ){
pInfo = sqlcipher_sqlite3DbMallocRawNN(pParse->db, sizeof(*pInfo));
- if( pInfo==0 ) return 0;
+ sqlcipher_sqlite3ParserAddCleanup(pToplevel, sqlcipher_sqlite3DbFree, pInfo);
+ testcase( pParse->earlyCleanup );
+ if( pParse->db->mallocFailed ) return 0;
pInfo->pNext = pToplevel->pAinc;
pToplevel->pAinc = pInfo;
pInfo->pTab = pTab;
@@ -126472,9 +132209,11 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Insert(
#endif
db = pParse->db;
- if( pParse->nErr || db->mallocFailed ){
+ assert( db->pParse==pParse );
+ if( pParse->nErr ){
goto insert_cleanup;
}
+ assert( db->mallocFailed==0 );
dest.iSDParm = 0; /* Suppress a harmless compiler warning */
/* If the Select object is really just a simple VALUES() list with a
@@ -126508,7 +132247,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Insert(
*/
#ifndef SQLITE_OMIT_TRIGGER
pTrigger = sqlcipher_sqlite3TriggersExist(pParse, pTab, TK_INSERT, 0, &tmask);
- isView = pTab->pSelect!=0;
+ isView = IsView(pTab);
#else
# define pTrigger 0
# define tmask 0
@@ -126520,6 +132259,14 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Insert(
#endif
assert( (pTrigger && tmask) || (pTrigger==0 && tmask==0) );
+#if TREETRACE_ENABLED
+ if( sqlcipher_sqlite3TreeTrace & 0x10000 ){
+ sqlcipher_sqlite3TreeViewLine(0, "In sqlcipher_sqlite3Insert() at %s:%d", __FILE__, __LINE__);
+ sqlcipher_sqlite3TreeViewInsert(pParse->pWith, pTabList, pColumn, pSelect, pList,
+ onError, pUpsert, pTrigger);
+ }
+#endif
+
/* If pTab is really a view, make sure it has been initialized.
** ViewGetColumnNames() is a no-op if pTab is not a view.
*/
@@ -126550,7 +132297,11 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Insert(
**
** This is the 2nd template.
*/
- if( pColumn==0 && xferOptimization(pParse, pTab, pSelect, onError, iDb) ){
+ if( pColumn==0
+ && pSelect!=0
+ && pTrigger==0
+ && xferOptimization(pParse, pTab, pSelect, onError, iDb)
+ ){
assert( !pTrigger );
assert( pList==0 );
goto insert_end;
@@ -126594,13 +132345,15 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Insert(
*/
bIdListInOrder = (pTab->tabFlags & (TF_OOOHidden|TF_HasStored))==0;
if( pColumn ){
+ assert( pColumn->eU4!=EU4_EXPR );
+ pColumn->eU4 = EU4_IDX;
for(i=0; i<pColumn->nId; i++){
- pColumn->a[i].idx = -1;
+ pColumn->a[i].u4.idx = -1;
}
for(i=0; i<pColumn->nId; i++){
for(j=0; j<pTab->nCol; j++){
- if( sqlcipher_sqlite3StrICmp(pColumn->a[i].zName, pTab->aCol[j].zName)==0 ){
- pColumn->a[i].idx = j;
+ if( sqlcipher_sqlite3StrICmp(pColumn->a[i].zName, pTab->aCol[j].zCnName)==0 ){
+ pColumn->a[i].u4.idx = j;
if( i!=j ) bIdListInOrder = 0;
if( j==pTab->iPKey ){
ipkColumn = i; assert( !withoutRowid );
@@ -126609,7 +132362,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Insert(
if( pTab->aCol[j].colFlags & (COLFLAG_STORED|COLFLAG_VIRTUAL) ){
sqlcipher_sqlite3ErrorMsg(pParse,
"cannot INSERT into generated column \"%s\"",
- pTab->aCol[j].zName);
+ pTab->aCol[j].zCnName);
goto insert_cleanup;
}
#endif
@@ -126622,7 +132375,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Insert(
bIdListInOrder = 0;
}else{
sqlcipher_sqlite3ErrorMsg(pParse, "table %S has no column named %s",
- pTabList, 0, pColumn->a[i].zName);
+ pTabList->a, pColumn->a[i].zName);
pParse->checkSchema = 1;
goto insert_cleanup;
}
@@ -126650,7 +132403,9 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Insert(
dest.nSdst = pTab->nCol;
rc = sqlcipher_sqlite3Select(pParse, pSelect, &dest);
regFromSelect = dest.iSdst;
- if( rc || db->mallocFailed || pParse->nErr ) goto insert_cleanup;
+ assert( db->pParse==pParse );
+ if( rc || pParse->nErr ) goto insert_cleanup;
+ assert( db->mallocFailed==0 );
sqlcipher_sqlite3VdbeEndCoroutine(v, regYield);
sqlcipher_sqlite3VdbeJumpHere(v, addrTop - 1); /* label B: */
assert( pSelect->pEList );
@@ -126735,19 +132490,24 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Insert(
}
}
#endif
- }
- /* Make sure the number of columns in the source data matches the number
- ** of columns to be inserted into the table.
- */
- for(i=0; i<pTab->nCol; i++){
- if( pTab->aCol[i].colFlags & COLFLAG_NOINSERT ) nHidden++;
- }
- if( pColumn==0 && nColumn && nColumn!=(pTab->nCol-nHidden) ){
- sqlcipher_sqlite3ErrorMsg(pParse,
- "table %S has %d columns but %d values were supplied",
- pTabList, 0, pTab->nCol-nHidden, nColumn);
- goto insert_cleanup;
+ /* Make sure the number of columns in the source data matches the number
+ ** of columns to be inserted into the table.
+ */
+ assert( TF_HasHidden==COLFLAG_HIDDEN );
+ assert( TF_HasGenerated==COLFLAG_GENERATED );
+ assert( COLFLAG_NOINSERT==(COLFLAG_GENERATED|COLFLAG_HIDDEN) );
+ if( (pTab->tabFlags & (TF_HasGenerated|TF_HasHidden))!=0 ){
+ for(i=0; i<pTab->nCol; i++){
+ if( pTab->aCol[i].colFlags & COLFLAG_NOINSERT ) nHidden++;
+ }
+ }
+ if( nColumn!=(pTab->nCol-nHidden) ){
+ sqlcipher_sqlite3ErrorMsg(pParse,
+ "table %S has %d columns but %d values were supplied",
+ pTabList->a, pTab->nCol-nHidden, nColumn);
+ goto insert_cleanup;
+ }
}
if( pColumn!=0 && nColumn!=pColumn->nId ){
sqlcipher_sqlite3ErrorMsg(pParse, "%d values for %d columns", nColumn, pColumn->nId);
@@ -126759,6 +132519,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Insert(
if( (db->flags & SQLITE_CountRows)!=0
&& !pParse->nested
&& !pParse->pTriggerTab
+ && !pParse->bReturning
){
regRowCount = ++pParse->nMem;
sqlcipher_sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount);
@@ -126782,12 +132543,13 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Insert(
}
#ifndef SQLITE_OMIT_UPSERT
if( pUpsert ){
+ Upsert *pNx;
if( IsVirtual(pTab) ){
sqlcipher_sqlite3ErrorMsg(pParse, "UPSERT not implemented for virtual table \"%s\"",
pTab->zName);
goto insert_cleanup;
}
- if( pTab->pSelect ){
+ if( IsView(pTab) ){
sqlcipher_sqlite3ErrorMsg(pParse, "cannot UPSERT a view");
goto insert_cleanup;
}
@@ -126795,13 +132557,19 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Insert(
goto insert_cleanup;
}
pTabList->a[0].iCursor = iDataCur;
- pUpsert->pUpsertSrc = pTabList;
- pUpsert->regData = regData;
- pUpsert->iDataCur = iDataCur;
- pUpsert->iIdxCur = iIdxCur;
- if( pUpsert->pUpsertTarget ){
- sqlcipher_sqlite3UpsertAnalyzeTarget(pParse, pTabList, pUpsert);
- }
+ pNx = pUpsert;
+ do{
+ pNx->pUpsertSrc = pTabList;
+ pNx->regData = regData;
+ pNx->iDataCur = iDataCur;
+ pNx->iIdxCur = iIdxCur;
+ if( pNx->pUpsertTarget ){
+ if( sqlcipher_sqlite3UpsertAnalyzeTarget(pParse, pTabList, pNx) ){
+ goto insert_cleanup;
+ }
+ }
+ pNx = pNx->pNextUpsert;
+ }while( pNx!=0 );
}
#endif
@@ -126880,22 +132648,29 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Insert(
}else if( pColumn==0 ){
/* Hidden columns that are not explicitly named in the INSERT
** get there default value */
- sqlcipher_sqlite3ExprCodeFactorable(pParse, pTab->aCol[i].pDflt, iRegStore);
+ sqlcipher_sqlite3ExprCodeFactorable(pParse,
+ sqlcipher_sqlite3ColumnExpr(pTab, &pTab->aCol[i]),
+ iRegStore);
continue;
}
}
if( pColumn ){
- for(j=0; j<pColumn->nId && pColumn->a[j].idx!=i; j++){}
+ assert( pColumn->eU4==EU4_IDX );
+ for(j=0; j<pColumn->nId && pColumn->a[j].u4.idx!=i; j++){}
if( j>=pColumn->nId ){
/* A column not named in the insert column list gets its
** default value */
- sqlcipher_sqlite3ExprCodeFactorable(pParse, pTab->aCol[i].pDflt, iRegStore);
+ sqlcipher_sqlite3ExprCodeFactorable(pParse,
+ sqlcipher_sqlite3ColumnExpr(pTab, &pTab->aCol[i]),
+ iRegStore);
continue;
}
k = j;
}else if( nColumn==0 ){
/* This is INSERT INTO ... DEFAULT VALUES. Load the default value. */
- sqlcipher_sqlite3ExprCodeFactorable(pParse, pTab->aCol[i].pDflt, iRegStore);
+ sqlcipher_sqlite3ExprCodeFactorable(pParse,
+ sqlcipher_sqlite3ColumnExpr(pTab, &pTab->aCol[i]),
+ iRegStore);
continue;
}else{
k = i - nHidden;
@@ -126942,11 +132717,6 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Insert(
sqlcipher_sqlite3VdbeAddOp1(v, OP_MustBeInt, regCols); VdbeCoverage(v);
}
- /* Cannot have triggers on a virtual table. If it were possible,
- ** this block would have to account for hidden column.
- */
- assert( !IsVirtual(pTab) );
-
/* Copy the new data already generated. */
assert( pTab->nNVCol>0 );
sqlcipher_sqlite3VdbeAddOp3(v, OP_Copy, regRowid+1, regCols+1, pTab->nNVCol-1);
@@ -127045,7 +132815,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Insert(
}else
#endif
{
- int isReplace; /* Set to true if constraints may cause a replace */
+ int isReplace = 0;/* Set to true if constraints may cause a replace */
int bUseSeek; /* True to use OPFLAG_SEEKRESULT */
sqlcipher_sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur,
regIns, 0, ipkColumn>=0, onError, endOfLoop, &isReplace, 0, pUpsert
@@ -127065,6 +132835,13 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Insert(
regIns, aRegIdx, 0, appendFlag, bUseSeek
);
}
+#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
+ }else if( pParse->bReturning ){
+ /* If there is a RETURNING clause, populate the rowid register with
+ ** constant value -1, in case one or more of the returned expressions
+ ** refer to the "rowid" of the view. */
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_Integer, -1, regRowid);
+#endif
}
/* Update the count of rows that are inserted
@@ -127101,7 +132878,9 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Insert(
sqlcipher_sqlite3VdbeJumpHere(v, addrInsTop);
}
+#ifndef SQLITE_OMIT_XFER_OPT
insert_end:
+#endif /* SQLITE_OMIT_XFER_OPT */
/* Update the sqlite_sequence table by storing the content of the
** maximum rowid counter values recorded while inserting into
** autoincrement tables.
@@ -127116,9 +132895,7 @@ insert_end:
** invoke the callback function.
*/
if( regRowCount ){
- sqlcipher_sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1);
- sqlcipher_sqlite3VdbeSetNumCols(v, 1);
- sqlcipher_sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows inserted", SQLITE_STATIC);
+ sqlcipher_sqlite3CodeChangeCount(v, regRowCount, "rows inserted");
}
insert_cleanup:
@@ -127207,6 +132984,70 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ExprReferencesUpdatedColumn(
}
/*
+** The sqlcipher_sqlite3GenerateConstraintChecks() routine usually wants to visit
+** the indexes of a table in the order provided in the Table->pIndex list.
+** However, sometimes (rarely - when there is an upsert) it wants to visit
+** the indexes in a different order. The following data structures accomplish
+** this.
+**
+** The IndexIterator object is used to walk through all of the indexes
+** of a table in either Index.pNext order, or in some other order established
+** by an array of IndexListTerm objects.
+*/
+typedef struct IndexListTerm IndexListTerm;
+typedef struct IndexIterator IndexIterator;
+struct IndexIterator {
+ int eType; /* 0 for Index.pNext list. 1 for an array of IndexListTerm */
+ int i; /* Index of the current item from the list */
+ union {
+ struct { /* Use this object for eType==0: A Index.pNext list */
+ Index *pIdx; /* The current Index */
+ } lx;
+ struct { /* Use this object for eType==1; Array of IndexListTerm */
+ int nIdx; /* Size of the array */
+ IndexListTerm *aIdx; /* Array of IndexListTerms */
+ } ax;
+ } u;
+};
+
+/* When IndexIterator.eType==1, then each index is an array of instances
+** of the following object
+*/
+struct IndexListTerm {
+ Index *p; /* The index */
+ int ix; /* Which entry in the original Table.pIndex list is this index*/
+};
+
+/* Return the first index on the list */
+static Index *indexIteratorFirst(IndexIterator *pIter, int *pIx){
+ assert( pIter->i==0 );
+ if( pIter->eType ){
+ *pIx = pIter->u.ax.aIdx[0].ix;
+ return pIter->u.ax.aIdx[0].p;
+ }else{
+ *pIx = 0;
+ return pIter->u.lx.pIdx;
+ }
+}
+
+/* Return the next index from the list. Return NULL when out of indexes */
+static Index *indexIteratorNext(IndexIterator *pIter, int *pIx){
+ if( pIter->eType ){
+ int i = ++pIter->i;
+ if( i>=pIter->u.ax.nIdx ){
+ *pIx = i;
+ return 0;
+ }
+ *pIx = pIter->u.ax.aIdx[i].ix;
+ return pIter->u.ax.aIdx[i].p;
+ }else{
+ ++(*pIx);
+ pIter->u.lx.pIdx = pIter->u.lx.pIdx->pNext;
+ return pIter->u.lx.pIdx;
+ }
+}
+
+/*
** Generate code to do constraint checks prior to an INSERT or an UPDATE
** on table pTab.
**
@@ -127314,7 +133155,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3GenerateConstraintChecks(
){
Vdbe *v; /* VDBE under constrution */
Index *pIdx; /* Pointer to one of the indices */
- Index *pPk = 0; /* The PRIMARY KEY index */
+ Index *pPk = 0; /* The PRIMARY KEY index for WITHOUT ROWID tables */
sqlcipher_sqlite3 *db; /* Database connection */
int i; /* loop counter */
int ix; /* Index loop counter */
@@ -127322,11 +133163,11 @@ SQLITE_PRIVATE void sqlcipher_sqlite3GenerateConstraintChecks(
int onError; /* Conflict resolution strategy */
int seenReplace = 0; /* True if REPLACE is used to resolve INT PK conflict */
int nPkField; /* Number of fields in PRIMARY KEY. 1 for ROWID tables */
- Index *pUpIdx = 0; /* Index to which to apply the upsert */
- u8 isUpdate; /* True if this is an UPDATE operation */
+ Upsert *pUpsertClause = 0; /* The specific ON CONFLICT clause for pIdx */
+ u8 isUpdate; /* True if this is an UPDATE operation */
u8 bAffinityDone = 0; /* True if the OP_Affinity operation has been run */
- int upsertBypass = 0; /* Address of Goto to bypass upsert subroutine */
- int upsertJump = 0; /* Address of Goto that jumps into upsert subroutine */
+ int upsertIpkReturn = 0; /* Address of Goto at end of IPK uniqueness check */
+ int upsertIpkDelay = 0; /* Address of Goto to bypass initial IPK check */
int ipkTop = 0; /* Top of the IPK uniqueness check */
int ipkBottom = 0; /* OP_Goto at the end of the IPK uniqueness check */
/* Variables associated with retesting uniqueness constraints after
@@ -127336,12 +133177,13 @@ SQLITE_PRIVATE void sqlcipher_sqlite3GenerateConstraintChecks(
int lblRecheckOk = 0; /* Each recheck jumps to this label if it passes */
Trigger *pTrigger; /* List of DELETE triggers on the table pTab */
int nReplaceTrig = 0; /* Number of replace triggers coded */
+ IndexIterator sIdxIter; /* Index iterator */
isUpdate = regOldData!=0;
db = pParse->db;
v = pParse->pVdbe;
assert( v!=0 );
- assert( pTab->pSelect==0 ); /* This table is not a VIEW */
+ assert( !IsView(pTab) ); /* This table is not a VIEW */
nCol = pTab->nCol;
/* pPk is the PRIMARY KEY index for WITHOUT ROWID tables and NULL for
@@ -127392,7 +133234,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3GenerateConstraintChecks(
}
if( onError==OE_Replace ){
if( b2ndPass /* REPLACE becomes ABORT on the 2nd pass */
- || pCol->pDflt==0 /* REPLACE is ABORT if no DEFAULT value */
+ || pCol->iDflt==0 /* REPLACE is ABORT if no DEFAULT value */
){
testcase( pCol->colFlags & COLFLAG_VIRTUAL );
testcase( pCol->colFlags & COLFLAG_STORED );
@@ -127414,7 +133256,8 @@ SQLITE_PRIVATE void sqlcipher_sqlite3GenerateConstraintChecks(
VdbeCoverage(v);
assert( (pCol->colFlags & COLFLAG_GENERATED)==0 );
nSeenReplace++;
- sqlcipher_sqlite3ExprCodeCopy(pParse, pCol->pDflt, iReg);
+ sqlcipher_sqlite3ExprCodeCopy(pParse,
+ sqlcipher_sqlite3ColumnExpr(pTab, pCol), iReg);
sqlcipher_sqlite3VdbeJumpHere(v, addr1);
break;
}
@@ -127424,7 +133267,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3GenerateConstraintChecks(
case OE_Rollback:
case OE_Fail: {
char *zMsg = sqlcipher_sqlite3MPrintf(db, "%s.%s", pTab->zName,
- pCol->zName);
+ pCol->zCnName);
sqlcipher_sqlite3VdbeAddOp3(v, OP_HaltIfNull, SQLITE_CONSTRAINT_NOTNULL,
onError, iReg);
sqlcipher_sqlite3VdbeAppendP4(v, zMsg, P4_DYNAMIC);
@@ -127533,19 +133376,63 @@ SQLITE_PRIVATE void sqlcipher_sqlite3GenerateConstraintChecks(
** list of indexes attached to a table puts all OE_Replace indexes last
** in the list. See sqlcipher_sqlite3CreateIndex() for where that happens.
*/
-
+ sIdxIter.eType = 0;
+ sIdxIter.i = 0;
+ sIdxIter.u.ax.aIdx = 0; /* Silence harmless compiler warning */
+ sIdxIter.u.lx.pIdx = pTab->pIndex;
if( pUpsert ){
if( pUpsert->pUpsertTarget==0 ){
- /* An ON CONFLICT DO NOTHING clause, without a constraint-target.
- ** Make all unique constraint resolution be OE_Ignore */
- assert( pUpsert->pUpsertSet==0 );
- overrideError = OE_Ignore;
- pUpsert = 0;
- }else if( (pUpIdx = pUpsert->pUpsertIdx)!=0 ){
- /* If the constraint-target uniqueness check must be run first.
- ** Jump to that uniqueness check now */
- upsertJump = sqlcipher_sqlite3VdbeAddOp0(v, OP_Goto);
- VdbeComment((v, "UPSERT constraint goes first"));
+ /* There is just on ON CONFLICT clause and it has no constraint-target */
+ assert( pUpsert->pNextUpsert==0 );
+ if( pUpsert->isDoUpdate==0 ){
+ /* A single ON CONFLICT DO NOTHING clause, without a constraint-target.
+ ** Make all unique constraint resolution be OE_Ignore */
+ overrideError = OE_Ignore;
+ pUpsert = 0;
+ }else{
+ /* A single ON CONFLICT DO UPDATE. Make all resolutions OE_Update */
+ overrideError = OE_Update;
+ }
+ }else if( pTab->pIndex!=0 ){
+ /* Otherwise, we'll need to run the IndexListTerm array version of the
+ ** iterator to ensure that all of the ON CONFLICT conditions are
+ ** checked first and in order. */
+ int nIdx, jj;
+ u64 nByte;
+ Upsert *pTerm;
+ u8 *bUsed;
+ for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){
+ assert( aRegIdx[nIdx]>0 );
+ }
+ sIdxIter.eType = 1;
+ sIdxIter.u.ax.nIdx = nIdx;
+ nByte = (sizeof(IndexListTerm)+1)*nIdx + nIdx;
+ sIdxIter.u.ax.aIdx = sqlcipher_sqlite3DbMallocZero(db, nByte);
+ if( sIdxIter.u.ax.aIdx==0 ) return; /* OOM */
+ bUsed = (u8*)&sIdxIter.u.ax.aIdx[nIdx];
+ pUpsert->pToFree = sIdxIter.u.ax.aIdx;
+ for(i=0, pTerm=pUpsert; pTerm; pTerm=pTerm->pNextUpsert){
+ if( pTerm->pUpsertTarget==0 ) break;
+ if( pTerm->pUpsertIdx==0 ) continue; /* Skip ON CONFLICT for the IPK */
+ jj = 0;
+ pIdx = pTab->pIndex;
+ while( ALWAYS(pIdx!=0) && pIdx!=pTerm->pUpsertIdx ){
+ pIdx = pIdx->pNext;
+ jj++;
+ }
+ if( bUsed[jj] ) continue; /* Duplicate ON CONFLICT clause ignored */
+ bUsed[jj] = 1;
+ sIdxIter.u.ax.aIdx[i].p = pIdx;
+ sIdxIter.u.ax.aIdx[i].ix = jj;
+ i++;
+ }
+ for(jj=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, jj++){
+ if( bUsed[jj] ) continue;
+ sIdxIter.u.ax.aIdx[i].p = pIdx;
+ sIdxIter.u.ax.aIdx[i].ix = jj;
+ i++;
+ }
+ assert( i==nIdx );
}
}
@@ -127608,11 +133495,20 @@ SQLITE_PRIVATE void sqlcipher_sqlite3GenerateConstraintChecks(
}
/* figure out whether or not upsert applies in this case */
- if( pUpsert && pUpsert->pUpsertIdx==0 ){
- if( pUpsert->pUpsertSet==0 ){
- onError = OE_Ignore; /* DO NOTHING is the same as INSERT OR IGNORE */
- }else{
- onError = OE_Update; /* DO UPDATE */
+ if( pUpsert ){
+ pUpsertClause = sqlcipher_sqlite3UpsertOfIndex(pUpsert,0);
+ if( pUpsertClause!=0 ){
+ if( pUpsertClause->isDoUpdate==0 ){
+ onError = OE_Ignore; /* DO NOTHING is the same as INSERT OR IGNORE */
+ }else{
+ onError = OE_Update; /* DO UPDATE */
+ }
+ }
+ if( pUpsertClause!=pUpsert ){
+ /* The first ON CONFLICT clause has a conflict target other than
+ ** the IPK. We have to jump ahead to that first ON CONFLICT clause
+ ** and then come back here and deal with the IPK afterwards */
+ upsertIpkDelay = sqlcipher_sqlite3VdbeAddOp0(v, OP_Goto);
}
}
@@ -127622,8 +133518,9 @@ SQLITE_PRIVATE void sqlcipher_sqlite3GenerateConstraintChecks(
** the UNIQUE constraints have run.
*/
if( onError==OE_Replace /* IPK rule is REPLACE */
- && onError!=overrideError /* Rules for other contraints are different */
+ && onError!=overrideError /* Rules for other constraints are different */
&& pTab->pIndex /* There exist other constraints */
+ && !upsertIpkDelay /* IPK check already deferred by UPSERT */
){
ipkTop = sqlcipher_sqlite3VdbeAddOp0(v, OP_Goto)+1;
VdbeComment((v, "defer IPK REPLACE until last"));
@@ -127719,7 +133616,9 @@ SQLITE_PRIVATE void sqlcipher_sqlite3GenerateConstraintChecks(
}
}
sqlcipher_sqlite3VdbeResolveLabel(v, addrRowidOk);
- if( ipkTop ){
+ if( pUpsert && pUpsertClause!=pUpsert ){
+ upsertIpkReturn = sqlcipher_sqlite3VdbeAddOp0(v, OP_Goto);
+ }else if( ipkTop ){
ipkBottom = sqlcipher_sqlite3VdbeAddOp0(v, OP_Goto);
sqlcipher_sqlite3VdbeJumpHere(v, ipkTop-1);
}
@@ -127732,7 +133631,10 @@ SQLITE_PRIVATE void sqlcipher_sqlite3GenerateConstraintChecks(
** 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++){
+ for(pIdx = indexIteratorFirst(&sIdxIter, &ix);
+ pIdx;
+ pIdx = indexIteratorNext(&sIdxIter, &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 */
@@ -127740,15 +133642,14 @@ SQLITE_PRIVATE void sqlcipher_sqlite3GenerateConstraintChecks(
int addrConflictCk; /* First opcode in the conflict check logic */
if( aRegIdx[ix]==0 ) continue; /* Skip indices that do not change */
- if( pUpIdx==pIdx ){
- addrUniqueOk = upsertJump+1;
- upsertBypass = sqlcipher_sqlite3VdbeGoto(v, 0);
- VdbeComment((v, "Skip upsert subroutine"));
- sqlcipher_sqlite3VdbeJumpHere(v, upsertJump);
- }else{
- addrUniqueOk = sqlcipher_sqlite3VdbeMakeLabel(pParse);
+ if( pUpsert ){
+ pUpsertClause = sqlcipher_sqlite3UpsertOfIndex(pUpsert, pIdx);
+ if( upsertIpkDelay && pUpsertClause==pUpsert ){
+ sqlcipher_sqlite3VdbeJumpHere(v, upsertIpkDelay);
+ }
}
- if( bAffinityDone==0 && (pUpIdx==0 || pUpIdx==pIdx) ){
+ addrUniqueOk = sqlcipher_sqlite3VdbeMakeLabel(pParse);
+ if( bAffinityDone==0 ){
sqlcipher_sqlite3TableAffinity(v, pTab, regNewData+1);
bAffinityDone = 1;
}
@@ -127785,7 +133686,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3GenerateConstraintChecks(
testcase( sqlcipher_sqlite3TableColumnToStorage(pTab, iField)!=iField );
x = sqlcipher_sqlite3TableColumnToStorage(pTab, iField) + regNewData + 1;
sqlcipher_sqlite3VdbeAddOp2(v, OP_SCopy, x, regIdx+i);
- VdbeComment((v, "%s", pTab->aCol[iField].zName));
+ VdbeComment((v, "%s", pTab->aCol[iField].zCnName));
}
}
sqlcipher_sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn, aRegIdx[ix]);
@@ -127819,8 +133720,8 @@ SQLITE_PRIVATE void sqlcipher_sqlite3GenerateConstraintChecks(
}
/* Figure out if the upsert clause applies to this index */
- if( pUpIdx==pIdx ){
- if( pUpsert->pUpsertSet==0 ){
+ if( pUpsertClause ){
+ if( pUpsertClause->isDoUpdate==0 ){
onError = OE_Ignore; /* DO NOTHING is the same as INSERT OR IGNORE */
}else{
onError = OE_Update; /* DO UPDATE */
@@ -127837,6 +133738,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3GenerateConstraintChecks(
** This is not possible for ENABLE_PREUPDATE_HOOK builds, as the row
** must be explicitly deleted in order to ensure any pre-update hook
** is invoked. */
+ assert( IsOrdinaryTable(pTab) );
#ifndef SQLITE_ENABLE_PREUPDATE_HOOK
if( (ix==0 && pIdx->pNext==0) /* Condition 3 */
&& pPk==pIdx /* Condition 2 */
@@ -127844,7 +133746,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3GenerateConstraintChecks(
&& ( 0==(db->flags&SQLITE_RecTriggers) || /* Condition 4 */
0==sqlcipher_sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0))
&& ( 0==(db->flags&SQLITE_ForeignKeys) || /* Condition 5 */
- (0==pTab->pFKey && 0==sqlcipher_sqlite3FkReferences(pTab)))
+ (0==pTab->u.tab.pFKey && 0==sqlcipher_sqlite3FkReferences(pTab)))
){
sqlcipher_sqlite3VdbeResolveLabel(v, addrUniqueOk);
continue;
@@ -127858,7 +133760,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3GenerateConstraintChecks(
regIdx, pIdx->nKeyCol); VdbeCoverage(v);
/* Generate code to handle collisions */
- regR = (pIdx==pPk) ? regIdx : sqlcipher_sqlite3GetTempRange(pParse, nPkField);
+ regR = pIdx==pPk ? regIdx : sqlcipher_sqlite3GetTempRange(pParse, nPkField);
if( isUpdate || onError==OE_Replace ){
if( HasRowid(pTab) ){
sqlcipher_sqlite3VdbeAddOp2(v, OP_IdxRowid, iThisCur, regR);
@@ -127879,13 +133781,13 @@ SQLITE_PRIVATE void sqlcipher_sqlite3GenerateConstraintChecks(
x = sqlcipher_sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[i]);
sqlcipher_sqlite3VdbeAddOp3(v, OP_Column, iThisCur, x, regR+i);
VdbeComment((v, "%s.%s", pTab->zName,
- pTab->aCol[pPk->aiColumn[i]].zName));
+ pTab->aCol[pPk->aiColumn[i]].zCnName));
}
}
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.
+ ** different from the old. See TH3 withoutrowid04.test.
**
** For a UNIQUE index, only conflict if the PRIMARY KEY values
** of the matched index row are different from the original PRIMARY
@@ -127943,7 +133845,8 @@ SQLITE_PRIVATE void sqlcipher_sqlite3GenerateConstraintChecks(
assert( onError==OE_Replace );
nConflictCk = sqlcipher_sqlite3VdbeCurrentAddr(v) - addrConflictCk;
- assert( nConflictCk>0 );
+ assert( nConflictCk>0 || db->mallocFailed );
+ testcase( nConflictCk<=0 );
testcase( nConflictCk>1 );
if( regTrigCnt ){
sqlcipher_sqlite3MultiWrite(pParse);
@@ -128010,19 +133913,23 @@ SQLITE_PRIVATE void sqlcipher_sqlite3GenerateConstraintChecks(
break;
}
}
- if( pUpIdx==pIdx ){
- sqlcipher_sqlite3VdbeGoto(v, upsertJump+1);
- sqlcipher_sqlite3VdbeJumpHere(v, upsertBypass);
- }else{
- sqlcipher_sqlite3VdbeResolveLabel(v, addrUniqueOk);
- }
+ sqlcipher_sqlite3VdbeResolveLabel(v, addrUniqueOk);
if( regR!=regIdx ) sqlcipher_sqlite3ReleaseTempRange(pParse, regR, nPkField);
+ if( pUpsertClause
+ && upsertIpkReturn
+ && sqlcipher_sqlite3UpsertNextIsIPK(pUpsertClause)
+ ){
+ sqlcipher_sqlite3VdbeGoto(v, upsertIpkDelay+1);
+ sqlcipher_sqlite3VdbeJumpHere(v, upsertIpkReturn);
+ upsertIpkReturn = 0;
+ }
}
/* If the IPK constraint is a REPLACE, run it last */
if( ipkTop ){
sqlcipher_sqlite3VdbeGoto(v, ipkTop);
VdbeComment((v, "Do IPK REPLACE"));
+ assert( ipkBottom>0 );
sqlcipher_sqlite3VdbeJumpHere(v, ipkBottom);
}
@@ -128075,7 +133982,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3SetMakeRecordP5(Vdbe *v, Table *pTab){
if( pTab->pSchema->file_format<2 ) return;
for(i=pTab->nCol-1; i>0; i--){
- if( pTab->aCol[i].pDflt!=0 ) break;
+ if( pTab->aCol[i].iDflt!=0 ) break;
if( pTab->aCol[i].colFlags & COLFLAG_PRIMKEY ) break;
}
sqlcipher_sqlite3VdbeChangeP5(v, i+1);
@@ -128083,6 +133990,32 @@ SQLITE_PRIVATE void sqlcipher_sqlite3SetMakeRecordP5(Vdbe *v, Table *pTab){
#endif
/*
+** Table pTab is a WITHOUT ROWID table that is being written to. The cursor
+** number is iCur, and register regData contains the new record for the
+** PK index. This function adds code to invoke the pre-update hook,
+** if one is registered.
+*/
+#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
+static void codeWithoutRowidPreupdate(
+ Parse *pParse, /* Parse context */
+ Table *pTab, /* Table being updated */
+ int iCur, /* Cursor number for table */
+ int regData /* Data containing new record */
+){
+ Vdbe *v = pParse->pVdbe;
+ int r = sqlcipher_sqlite3GetTempReg(pParse);
+ assert( !HasRowid(pTab) );
+ assert( 0==(pParse->db->mDbFlags & DBFLAG_Vacuum) || CORRUPT_DB );
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_Integer, 0, r);
+ sqlcipher_sqlite3VdbeAddOp4(v, OP_Insert, iCur, regData, r, (char*)pTab, P4_TABLE);
+ sqlcipher_sqlite3VdbeChangeP5(v, OPFLAG_ISNOOP);
+ sqlcipher_sqlite3ReleaseTempReg(pParse, r);
+}
+#else
+# define codeWithoutRowidPreupdate(a,b,c,d)
+#endif
+
+/*
** This routine generates code to finish the INSERT or UPDATE operation
** that was started by a prior call to sqlcipher_sqlite3GenerateConstraintChecks.
** A consecutive range of registers starting at regNewData contains the
@@ -128114,7 +134047,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3CompleteInsertion(
v = pParse->pVdbe;
assert( v!=0 );
- assert( pTab->pSelect==0 ); /* This table is not a VIEW */
+ assert( !IsView(pTab) ); /* This table is not a VIEW */
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
/* All REPLACE indexes are at the end of the list */
assert( pIdx->onError!=OE_Replace
@@ -128127,20 +134060,11 @@ SQLITE_PRIVATE void sqlcipher_sqlite3CompleteInsertion(
}
pik_flags = (useSeekResult ? OPFLAG_USESEEKRESULT : 0);
if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){
- assert( pParse->nested==0 );
pik_flags |= OPFLAG_NCHANGE;
pik_flags |= (update_flags & OPFLAG_SAVEPOSITION);
-#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
if( update_flags==0 ){
- int r = sqlcipher_sqlite3GetTempReg(pParse);
- sqlcipher_sqlite3VdbeAddOp2(v, OP_Integer, 0, r);
- sqlcipher_sqlite3VdbeAddOp4(v, OP_Insert,
- iIdxCur+i, aRegIdx[i], r, (char*)pTab, P4_TABLE
- );
- sqlcipher_sqlite3VdbeChangeP5(v, OPFLAG_ISNOOP);
- sqlcipher_sqlite3ReleaseTempReg(pParse, r);
+ codeWithoutRowidPreupdate(pParse, pTab, iIdxCur+i, aRegIdx[i]);
}
-#endif
}
sqlcipher_sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iIdxCur+i, aRegIdx[i],
aRegIdx[i]+1,
@@ -128208,8 +134132,9 @@ SQLITE_PRIVATE int sqlcipher_sqlite3OpenTableAndIndices(
assert( op==OP_OpenWrite || p5==0 );
if( IsVirtual(pTab) ){
/* This routine is a no-op for virtual tables. Leave the output
- ** variables *piDataCur and *piIdxCur uninitialized so that valgrind
- ** can detect if they are used by mistake in the caller. */
+ ** variables *piDataCur and *piIdxCur set to illegal cursor numbers
+ ** for improved error detection. */
+ *piDataCur = *piIdxCur = -999;
return 0;
}
iDb = sqlcipher_sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
@@ -128338,7 +134263,7 @@ static int xferOptimization(
ExprList *pEList; /* The result set of the SELECT */
Table *pSrc; /* The table in the FROM clause of SELECT */
Index *pSrcIdx, *pDestIdx; /* Source and destination indices */
- struct SrcList_item *pItem; /* An element of pSelect->pSrc */
+ SrcItem *pItem; /* An element of pSelect->pSrc */
int i; /* Loop counter */
int iDbSrc; /* The database of pSrc */
int iSrc, iDest; /* Cursors from source and destination */
@@ -128350,18 +134275,13 @@ static int xferOptimization(
int destHasUniqueIdx = 0; /* True if pDest has a UNIQUE index */
int regData, regRowid; /* Registers holding data and rowid */
- if( pSelect==0 ){
- return 0; /* Must be of the form INSERT INTO ... SELECT ... */
- }
+ assert( pSelect!=0 );
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( sqlcipher_sqlite3TriggerList(pParse, pDest) ){
- return 0; /* tab1 must not have triggers */
- }
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( IsVirtual(pDest) ){
return 0; /* tab1 must not be a virtual table */
@@ -128424,13 +134344,8 @@ static int xferOptimization(
if( HasRowid(pDest)!=HasRowid(pSrc) ){
return 0; /* source and destination must both be WITHOUT ROWID or not */
}
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( IsVirtual(pSrc) ){
- return 0; /* tab2 must not be a virtual table */
- }
-#endif
- if( pSrc->pSelect ){
- return 0; /* tab2 may not be a view */
+ if( !IsOrdinaryTable(pSrc) ){
+ return 0; /* tab2 may not be a view or virtual table */
}
if( pDest->nCol!=pSrc->nCol ){
return 0; /* Number of columns must be the same in tab1 and tab2 */
@@ -128438,6 +134353,9 @@ static int xferOptimization(
if( pDest->iPKey!=pSrc->iPKey ){
return 0; /* Both tables must have the same INTEGER PRIMARY KEY */
}
+ if( (pDest->tabFlags & TF_Strict)!=0 && (pSrc->tabFlags & TF_Strict)==0 ){
+ return 0; /* Cannot feed from a non-strict into a strict table */
+ }
for(i=0; i<pDest->nCol; i++){
Column *pDestCol = &pDest->aCol[i];
Column *pSrcCol = &pSrc->aCol[i];
@@ -128474,7 +134392,9 @@ static int xferOptimization(
** This requirement could be relaxed for VIRTUAL columns, I suppose.
*/
if( (pDestCol->colFlags & COLFLAG_GENERATED)!=0 ){
- if( sqlcipher_sqlite3ExprCompare(0, pSrcCol->pDflt, pDestCol->pDflt, -1)!=0 ){
+ if( sqlcipher_sqlite3ExprCompare(0,
+ sqlcipher_sqlite3ColumnExpr(pSrc, pSrcCol),
+ sqlcipher_sqlite3ColumnExpr(pDest, pDestCol), -1)!=0 ){
testcase( pDestCol->colFlags & COLFLAG_VIRTUAL );
testcase( pDestCol->colFlags & COLFLAG_STORED );
return 0; /* Different generator expressions */
@@ -128484,7 +134404,8 @@ static int xferOptimization(
if( pDestCol->affinity!=pSrcCol->affinity ){
return 0; /* Affinity must be the same on all columns */
}
- if( sqlcipher_sqlite3_stricmp(pDestCol->zColl, pSrcCol->zColl)!=0 ){
+ if( sqlcipher_sqlite3_stricmp(sqlcipher_sqlite3ColumnColl(pDestCol),
+ sqlcipher_sqlite3ColumnColl(pSrcCol))!=0 ){
return 0; /* Collating sequence must be the same on all columns */
}
if( pDestCol->notNull && !pSrcCol->notNull ){
@@ -128492,11 +134413,15 @@ static int xferOptimization(
}
/* Default values for second and subsequent columns need to match. */
if( (pDestCol->colFlags & COLFLAG_GENERATED)==0 && i>0 ){
- assert( pDestCol->pDflt==0 || pDestCol->pDflt->op==TK_SPAN );
- assert( pSrcCol->pDflt==0 || pSrcCol->pDflt->op==TK_SPAN );
- if( (pDestCol->pDflt==0)!=(pSrcCol->pDflt==0)
- || (pDestCol->pDflt && strcmp(pDestCol->pDflt->u.zToken,
- pSrcCol->pDflt->u.zToken)!=0)
+ Expr *pDestExpr = sqlcipher_sqlite3ColumnExpr(pDest, pDestCol);
+ Expr *pSrcExpr = sqlcipher_sqlite3ColumnExpr(pSrc, pSrcCol);
+ assert( pDestExpr==0 || pDestExpr->op==TK_SPAN );
+ assert( pDestExpr==0 || !ExprHasProperty(pDestExpr, EP_IntValue) );
+ assert( pSrcExpr==0 || pSrcExpr->op==TK_SPAN );
+ assert( pSrcExpr==0 || !ExprHasProperty(pSrcExpr, EP_IntValue) );
+ if( (pDestExpr==0)!=(pSrcExpr==0)
+ || (pDestExpr!=0 && strcmp(pDestExpr->u.zToken,
+ pSrcExpr->u.zToken)!=0)
){
return 0; /* Default values must be the same for all columns */
}
@@ -128533,7 +134458,8 @@ static int xferOptimization(
** the extra complication to make this rule less restrictive is probably
** not worth the effort. Ticket [6284df89debdfa61db8073e062908af0c9b6118e]
*/
- if( (db->flags & SQLITE_ForeignKeys)!=0 && pDest->pFKey!=0 ){
+ assert( IsOrdinaryTable(pDest) );
+ if( (db->flags & SQLITE_ForeignKeys)!=0 && pDest->u.tab.pFKey!=0 ){
return 0;
}
#endif
@@ -128555,6 +134481,7 @@ static int xferOptimization(
iDest = pParse->nTab++;
regAutoinc = autoIncBegin(pParse, iDbDest, pDest);
regData = sqlcipher_sqlite3GetTempReg(pParse);
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_Null, 0, regData);
regRowid = sqlcipher_sqlite3GetTempReg(pParse);
sqlcipher_sqlite3OpenTable(pParse, iDest, iDbDest, pDest, OP_OpenWrite);
assert( HasRowid(pDest) || destHasUniqueIdx );
@@ -128590,11 +134517,13 @@ static int xferOptimization(
emptySrcTest = sqlcipher_sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v);
if( pDest->iPKey>=0 ){
addr1 = sqlcipher_sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
- sqlcipher_sqlite3VdbeVerifyAbortable(v, onError);
- addr2 = sqlcipher_sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid);
- VdbeCoverage(v);
- sqlcipher_sqlite3RowidConstraint(pParse, onError, pDest);
- sqlcipher_sqlite3VdbeJumpHere(v, addr2);
+ if( (db->mDbFlags & DBFLAG_Vacuum)==0 ){
+ sqlcipher_sqlite3VdbeVerifyAbortable(v, onError);
+ addr2 = sqlcipher_sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid);
+ VdbeCoverage(v);
+ sqlcipher_sqlite3RowidConstraint(pParse, onError, pDest);
+ sqlcipher_sqlite3VdbeJumpHere(v, addr2);
+ }
autoIncStep(pParse, regAutoinc, regRowid);
}else if( pDest->pIndex==0 && !(db->mDbFlags & DBFLAG_VacuumInto) ){
addr1 = sqlcipher_sqlite3VdbeAddOp2(v, OP_NewRowid, iDest, regRowid);
@@ -128602,16 +134531,28 @@ static int xferOptimization(
addr1 = sqlcipher_sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
assert( (pDest->tabFlags & TF_Autoincrement)==0 );
}
+
if( db->mDbFlags & DBFLAG_Vacuum ){
sqlcipher_sqlite3VdbeAddOp1(v, OP_SeekEnd, iDest);
- insFlags = OPFLAG_APPEND|OPFLAG_USESEEKRESULT;
+ insFlags = OPFLAG_APPEND|OPFLAG_USESEEKRESULT|OPFLAG_PREFORMAT;
}else{
- insFlags = OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND;
+ insFlags = OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND|OPFLAG_PREFORMAT;
+ }
+#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
+ if( (db->mDbFlags & DBFLAG_Vacuum)==0 ){
+ sqlcipher_sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1);
+ insFlags &= ~OPFLAG_PREFORMAT;
+ }else
+#endif
+ {
+ sqlcipher_sqlite3VdbeAddOp3(v, OP_RowCell, iDest, iSrc, regRowid);
+ }
+ sqlcipher_sqlite3VdbeAddOp3(v, OP_Insert, iDest, regData, regRowid);
+ if( (db->mDbFlags & DBFLAG_Vacuum)==0 ){
+ sqlcipher_sqlite3VdbeChangeP4(v, -1, (char*)pDest, P4_TABLE);
}
- sqlcipher_sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1);
- sqlcipher_sqlite3VdbeAddOp4(v, OP_Insert, iDest, regData, regRowid,
- (char*)pDest, P4_TABLE);
sqlcipher_sqlite3VdbeChangeP5(v, insFlags);
+
sqlcipher_sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1); VdbeCoverage(v);
sqlcipher_sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0);
sqlcipher_sqlite3VdbeAddOp2(v, OP_Close, iDest, 0);
@@ -128653,13 +134594,22 @@ static int xferOptimization(
if( sqlcipher_sqlite3_stricmp(sqlcipher_sqlite3StrBINARY, zColl) ) break;
}
if( i==pSrcIdx->nColumn ){
- idxInsFlags = OPFLAG_USESEEKRESULT;
+ idxInsFlags = OPFLAG_USESEEKRESULT|OPFLAG_PREFORMAT;
sqlcipher_sqlite3VdbeAddOp1(v, OP_SeekEnd, iDest);
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_RowCell, iDest, iSrc);
}
}else if( !HasRowid(pSrc) && pDestIdx->idxType==SQLITE_IDXTYPE_PRIMARYKEY ){
idxInsFlags |= OPFLAG_NCHANGE;
}
- sqlcipher_sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1);
+ if( idxInsFlags!=(OPFLAG_USESEEKRESULT|OPFLAG_PREFORMAT) ){
+ sqlcipher_sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1);
+ if( (db->mDbFlags & DBFLAG_Vacuum)==0
+ && !HasRowid(pDest)
+ && IsPrimaryKeyIndex(pDestIdx)
+ ){
+ codeWithoutRowidPreupdate(pParse, pDest, iDest, regData);
+ }
+ }
sqlcipher_sqlite3VdbeAddOp2(v, OP_IdxInsert, iDest, regData);
sqlcipher_sqlite3VdbeChangeP5(v, idxInsFlags|OPFLAG_APPEND);
sqlcipher_sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1); VdbeCoverage(v);
@@ -129187,6 +135137,26 @@ struct sqlcipher_sqlite3_api_routines {
sqlcipher_sqlite3_file *(*database_file_object)(const char*);
/* Version 3.34.0 and later */
int (*txn_state)(sqlcipher_sqlite3*,const char*);
+ /* Version 3.36.1 and later */
+ sqlcipher_sqlite3_int64 (*changes64)(sqlcipher_sqlite3*);
+ sqlcipher_sqlite3_int64 (*total_changes64)(sqlcipher_sqlite3*);
+ /* Version 3.37.0 and later */
+ int (*autovacuum_pages)(sqlcipher_sqlite3*,
+ unsigned int(*)(void*,const char*,unsigned int,unsigned int,unsigned int),
+ void*, void(*)(void*));
+ /* Version 3.38.0 and later */
+ int (*error_offset)(sqlcipher_sqlite3*);
+ int (*vtab_rhs_value)(sqlcipher_sqlite3_index_info*,int,sqlcipher_sqlite3_value**);
+ int (*vtab_distinct)(sqlcipher_sqlite3_index_info*);
+ int (*vtab_in)(sqlcipher_sqlite3_index_info*,int,int);
+ int (*vtab_in_first)(sqlcipher_sqlite3_value*,sqlcipher_sqlite3_value**);
+ int (*vtab_in_next)(sqlcipher_sqlite3_value*,sqlcipher_sqlite3_value**);
+ /* Version 3.39.0 and later */
+ int (*deserialize)(sqlcipher_sqlite3*,const char*,unsigned char*,
+ sqlcipher_sqlite3_int64,sqlcipher_sqlite3_int64,unsigned);
+ unsigned char *(*serialize)(sqlcipher_sqlite3*,const char *,sqlcipher_sqlite3_int64*,
+ unsigned int);
+ const char *(*db_name)(sqlcipher_sqlite3*,int);
};
/*
@@ -129493,6 +135463,24 @@ typedef int (*sqlcipher_sqlite3_loadext_entry)(
#define sqlcipher_sqlite3_database_file_object sqlcipher_sqlite3_api->database_file_object
/* Version 3.34.0 and later */
#define sqlcipher_sqlite3_txn_state sqlcipher_sqlite3_api->txn_state
+/* Version 3.36.1 and later */
+#define sqlcipher_sqlite3_changes64 sqlcipher_sqlite3_api->changes64
+#define sqlcipher_sqlite3_total_changes64 sqlcipher_sqlite3_api->total_changes64
+/* Version 3.37.0 and later */
+#define sqlcipher_sqlite3_autovacuum_pages sqlcipher_sqlite3_api->autovacuum_pages
+/* Version 3.38.0 and later */
+#define sqlcipher_sqlite3_error_offset sqlcipher_sqlite3_api->error_offset
+#define sqlcipher_sqlite3_vtab_rhs_value sqlcipher_sqlite3_api->vtab_rhs_value
+#define sqlcipher_sqlite3_vtab_distinct sqlcipher_sqlite3_api->vtab_distinct
+#define sqlcipher_sqlite3_vtab_in sqlcipher_sqlite3_api->vtab_in
+#define sqlcipher_sqlite3_vtab_in_first sqlcipher_sqlite3_api->vtab_in_first
+#define sqlcipher_sqlite3_vtab_in_next sqlcipher_sqlite3_api->vtab_in_next
+/* Version 3.39.0 and later */
+#ifndef SQLITE_OMIT_DESERIALIZE
+#define sqlcipher_sqlite3_deserialize sqlcipher_sqlite3_api->deserialize
+#define sqlcipher_sqlite3_serialize sqlcipher_sqlite3_api->serialize
+#endif
+#define sqlcipher_sqlite3_db_name sqlcipher_sqlite3_api->db_name
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
@@ -129977,6 +135965,35 @@ static const sqlcipher_sqlite3_api_routines sqlcipher_sqlite3Apis = {
sqlcipher_sqlite3_database_file_object,
/* Version 3.34.0 and later */
sqlcipher_sqlite3_txn_state,
+ /* Version 3.36.1 and later */
+ sqlcipher_sqlite3_changes64,
+ sqlcipher_sqlite3_total_changes64,
+ /* Version 3.37.0 and later */
+ sqlcipher_sqlite3_autovacuum_pages,
+ /* Version 3.38.0 and later */
+ sqlcipher_sqlite3_error_offset,
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ sqlcipher_sqlite3_vtab_rhs_value,
+ sqlcipher_sqlite3_vtab_distinct,
+ sqlcipher_sqlite3_vtab_in,
+ sqlcipher_sqlite3_vtab_in_first,
+ sqlcipher_sqlite3_vtab_in_next,
+#else
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+#endif
+ /* Version 3.39.0 and later */
+#ifndef SQLITE_OMIT_DESERIALIZE
+ sqlcipher_sqlite3_deserialize,
+ sqlcipher_sqlite3_serialize,
+#else
+ 0,
+ 0,
+#endif
+ sqlcipher_sqlite3_db_name
};
/* True if x is the directory separator character
@@ -130012,7 +136029,7 @@ static int sqlcipher_sqlite3LoadExtension(
const char *zEntry;
char *zAltEntry = 0;
void **aHandle;
- u64 nMsg = 300 + sqlcipher_sqlite3Strlen30(zFile);
+ u64 nMsg = strlen(zFile);
int ii;
int rc;
@@ -130046,6 +136063,12 @@ static int sqlcipher_sqlite3LoadExtension(
zEntry = zProc ? zProc : "sqlcipher_sqlite3_extension_init";
+ /* tag-20210611-1. Some dlopen() implementations will segfault if given
+ ** an oversize filename. Most filesystems have a pathname limit of 4K,
+ ** so limit the extension filename length to about twice that.
+ ** https://sqlite.org/forum/forumpost/08a0d6d9bf */
+ if( nMsg>SQLITE_MAX_PATHLEN ) goto extension_not_found;
+
handle = sqlcipher_sqlite3OsDlOpen(pVfs, zFile);
#if SQLITE_OS_UNIX || SQLITE_OS_WIN
for(ii=0; ii<ArraySize(azEndings) && handle==0; ii++){
@@ -130055,17 +136078,7 @@ static int sqlcipher_sqlite3LoadExtension(
sqlcipher_sqlite3_free(zAltFile);
}
#endif
- if( handle==0 ){
- if( pzErrMsg ){
- *pzErrMsg = zErrmsg = sqlcipher_sqlite3_malloc64(nMsg);
- if( zErrmsg ){
- sqlcipher_sqlite3_snprintf(nMsg, zErrmsg,
- "unable to open shared library [%s]", zFile);
- sqlcipher_sqlite3OsDlError(pVfs, nMsg-1, zErrmsg);
- }
- }
- return SQLITE_ERROR;
- }
+ if( handle==0 ) goto extension_not_found;
xInit = (sqlcipher_sqlite3_loadext_entry)sqlcipher_sqlite3OsDlSym(pVfs, handle, zEntry);
/* If no entry point was specified and the default legacy
@@ -130102,10 +136115,11 @@ static int sqlcipher_sqlite3LoadExtension(
}
if( xInit==0 ){
if( pzErrMsg ){
- nMsg += sqlcipher_sqlite3Strlen30(zEntry);
+ nMsg += strlen(zEntry) + 300;
*pzErrMsg = zErrmsg = sqlcipher_sqlite3_malloc64(nMsg);
if( zErrmsg ){
- sqlcipher_sqlite3_snprintf(nMsg, zErrmsg,
+ assert( nMsg<0x7fffffff ); /* zErrmsg would be NULL if not so */
+ sqlcipher_sqlite3_snprintf((int)nMsg, zErrmsg,
"no entry point [%s] in shared library [%s]", zEntry, zFile);
sqlcipher_sqlite3OsDlError(pVfs, nMsg-1, zErrmsg);
}
@@ -130139,6 +136153,19 @@ static int sqlcipher_sqlite3LoadExtension(
db->aExtension[db->nExtension++] = handle;
return SQLITE_OK;
+
+extension_not_found:
+ if( pzErrMsg ){
+ nMsg += 300;
+ *pzErrMsg = zErrmsg = sqlcipher_sqlite3_malloc64(nMsg);
+ if( zErrmsg ){
+ assert( nMsg<0x7fffffff ); /* zErrmsg would be NULL if not so */
+ sqlcipher_sqlite3_snprintf((int)nMsg, zErrmsg,
+ "unable to open shared library [%.*s]", SQLITE_MAX_PATHLEN, zFile);
+ sqlcipher_sqlite3OsDlError(pVfs, nMsg-1, zErrmsg);
+ }
+ }
+ return SQLITE_ERROR;
}
SQLITE_API int sqlcipher_sqlite3_load_extension(
sqlcipher_sqlite3 *db, /* Load the extension into this database connection */
@@ -130430,13 +136457,14 @@ SQLITE_PRIVATE void sqlcipher_sqlite3AutoLoadExtensions(sqlcipher_sqlite3 *db){
#define PragTyp_SOFT_HEAP_LIMIT 35
#define PragTyp_SYNCHRONOUS 36
#define PragTyp_TABLE_INFO 37
-#define PragTyp_TEMP_STORE 38
-#define PragTyp_TEMP_STORE_DIRECTORY 39
-#define PragTyp_THREADS 40
-#define PragTyp_WAL_AUTOCHECKPOINT 41
-#define PragTyp_WAL_CHECKPOINT 42
-#define PragTyp_LOCK_STATUS 43
-#define PragTyp_STATS 44
+#define PragTyp_TABLE_LIST 38
+#define PragTyp_TEMP_STORE 39
+#define PragTyp_TEMP_STORE_DIRECTORY 40
+#define PragTyp_THREADS 41
+#define PragTyp_WAL_AUTOCHECKPOINT 42
+#define PragTyp_WAL_CHECKPOINT 43
+#define PragTyp_LOCK_STATUS 44
+#define PragTyp_STATS 45
/* Property flags associated with various pragma. */
#define PragFlg_NeedSchema 0x01 /* Force schema load before running */
@@ -130469,45 +136497,51 @@ static const char *const pragCName[] = {
/* 13 */ "pk",
/* 14 */ "hidden",
/* table_info reuses 8 */
- /* 15 */ "seqno", /* Used by: index_xinfo */
- /* 16 */ "cid",
- /* 17 */ "name",
- /* 18 */ "desc",
- /* 19 */ "coll",
- /* 20 */ "key",
- /* 21 */ "name", /* Used by: function_list */
- /* 22 */ "builtin",
- /* 23 */ "type",
- /* 24 */ "enc",
- /* 25 */ "narg",
- /* 26 */ "flags",
- /* 27 */ "tbl", /* Used by: stats */
- /* 28 */ "idx",
- /* 29 */ "wdth",
- /* 30 */ "hght",
- /* 31 */ "flgs",
- /* 32 */ "seq", /* Used by: index_list */
- /* 33 */ "name",
- /* 34 */ "unique",
- /* 35 */ "origin",
- /* 36 */ "partial",
- /* 37 */ "table", /* Used by: foreign_key_check */
- /* 38 */ "rowid",
- /* 39 */ "parent",
- /* 40 */ "fkid",
- /* index_info reuses 15 */
- /* 41 */ "seq", /* Used by: database_list */
- /* 42 */ "name",
- /* 43 */ "file",
- /* 44 */ "busy", /* Used by: wal_checkpoint */
- /* 45 */ "log",
- /* 46 */ "checkpointed",
- /* collation_list reuses 32 */
- /* 47 */ "database", /* Used by: lock_status */
- /* 48 */ "status",
- /* 49 */ "cache_size", /* Used by: default_cache_size */
+ /* 15 */ "schema", /* Used by: table_list */
+ /* 16 */ "name",
+ /* 17 */ "type",
+ /* 18 */ "ncol",
+ /* 19 */ "wr",
+ /* 20 */ "strict",
+ /* 21 */ "seqno", /* Used by: index_xinfo */
+ /* 22 */ "cid",
+ /* 23 */ "name",
+ /* 24 */ "desc",
+ /* 25 */ "coll",
+ /* 26 */ "key",
+ /* 27 */ "name", /* Used by: function_list */
+ /* 28 */ "builtin",
+ /* 29 */ "type",
+ /* 30 */ "enc",
+ /* 31 */ "narg",
+ /* 32 */ "flags",
+ /* 33 */ "tbl", /* Used by: stats */
+ /* 34 */ "idx",
+ /* 35 */ "wdth",
+ /* 36 */ "hght",
+ /* 37 */ "flgs",
+ /* 38 */ "seq", /* Used by: index_list */
+ /* 39 */ "name",
+ /* 40 */ "unique",
+ /* 41 */ "origin",
+ /* 42 */ "partial",
+ /* 43 */ "table", /* Used by: foreign_key_check */
+ /* 44 */ "rowid",
+ /* 45 */ "parent",
+ /* 46 */ "fkid",
+ /* index_info reuses 21 */
+ /* 47 */ "seq", /* Used by: database_list */
+ /* 48 */ "name",
+ /* 49 */ "file",
+ /* 50 */ "busy", /* Used by: wal_checkpoint */
+ /* 51 */ "log",
+ /* 52 */ "checkpointed",
+ /* collation_list reuses 38 */
+ /* 53 */ "database", /* Used by: lock_status */
+ /* 54 */ "status",
+ /* 55 */ "cache_size", /* Used by: default_cache_size */
/* module_list pragma_list reuses 9 */
- /* 50 */ "timeout", /* Used by: busy_timeout */
+ /* 56 */ "timeout", /* Used by: busy_timeout */
};
/* Definitions of all built-in pragmas */
@@ -130558,7 +136592,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "busy_timeout",
/* ePragTyp: */ PragTyp_BUSY_TIMEOUT,
/* ePragFlg: */ PragFlg_Result0,
- /* ColNames: */ 50, 1,
+ /* ColNames: */ 56, 1,
/* iArg: */ 0 },
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
{/* zName: */ "cache_size",
@@ -130597,7 +136631,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "collation_list",
/* ePragTyp: */ PragTyp_COLLATION_LIST,
/* ePragFlg: */ PragFlg_Result0,
- /* ColNames: */ 32, 2,
+ /* ColNames: */ 38, 2,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS)
@@ -130631,15 +136665,15 @@ static const PragmaName aPragmaName[] = {
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
{/* zName: */ "database_list",
/* ePragTyp: */ PragTyp_DATABASE_LIST,
- /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0,
- /* ColNames: */ 41, 3,
+ /* ePragFlg: */ PragFlg_Result0,
+ /* ColNames: */ 47, 3,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
{/* zName: */ "default_cache_size",
/* ePragTyp: */ PragTyp_DEFAULT_CACHE_SIZE,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1,
- /* ColNames: */ 49, 1,
+ /* ColNames: */ 55, 1,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
@@ -130669,7 +136703,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "foreign_key_check",
/* ePragTyp: */ PragTyp_FOREIGN_KEY_CHECK,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_Result1|PragFlg_SchemaOpt,
- /* ColNames: */ 37, 4,
+ /* ColNames: */ 43, 4,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FOREIGN_KEY)
@@ -130712,7 +136746,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "function_list",
/* ePragTyp: */ PragTyp_FUNCTION_LIST,
/* ePragFlg: */ PragFlg_Result0,
- /* ColNames: */ 21, 6,
+ /* ColNames: */ 27, 6,
/* iArg: */ 0 },
#endif
#endif
@@ -130755,23 +136789,23 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "index_info",
/* ePragTyp: */ PragTyp_INDEX_INFO,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
- /* ColNames: */ 15, 3,
+ /* ColNames: */ 21, 3,
/* iArg: */ 0 },
{/* zName: */ "index_list",
/* ePragTyp: */ PragTyp_INDEX_LIST,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
- /* ColNames: */ 32, 5,
+ /* ColNames: */ 38, 5,
/* iArg: */ 0 },
{/* zName: */ "index_xinfo",
/* ePragTyp: */ PragTyp_INDEX_INFO,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
- /* ColNames: */ 15, 6,
+ /* ColNames: */ 21, 6,
/* iArg: */ 1 },
#endif
#if !defined(SQLITE_OMIT_INTEGRITY_CHECK)
{/* zName: */ "integrity_check",
/* ePragTyp: */ PragTyp_INTEGRITY_CHECK,
- /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_Result1,
+ /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_Result1|PragFlg_SchemaOpt,
/* ColNames: */ 0, 0,
/* iArg: */ 0 },
#endif
@@ -130814,7 +136848,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "lock_status",
/* ePragTyp: */ PragTyp_LOCK_STATUS,
/* ePragFlg: */ PragFlg_Result0,
- /* ColNames: */ 47, 2,
+ /* ColNames: */ 53, 2,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
@@ -130888,7 +136922,7 @@ static const PragmaName aPragmaName[] = {
#if !defined(SQLITE_OMIT_INTEGRITY_CHECK)
{/* zName: */ "quick_check",
/* ePragTyp: */ PragTyp_INTEGRITY_CHECK,
- /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_Result1,
+ /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_Result1|PragFlg_SchemaOpt,
/* ColNames: */ 0, 0,
/* iArg: */ 0 },
#endif
@@ -130964,7 +136998,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "stats",
/* ePragTyp: */ PragTyp_STATS,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq,
- /* ColNames: */ 27, 5,
+ /* ColNames: */ 33, 5,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
@@ -130980,6 +137014,11 @@ static const PragmaName aPragmaName[] = {
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
/* ColNames: */ 8, 6,
/* iArg: */ 0 },
+ {/* zName: */ "table_list",
+ /* ePragTyp: */ PragTyp_TABLE_LIST,
+ /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1,
+ /* ColNames: */ 15, 6,
+ /* iArg: */ 0 },
{/* zName: */ "table_xinfo",
/* ePragTyp: */ PragTyp_TABLE_INFO,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
@@ -131069,7 +137108,7 @@ static const PragmaName aPragmaName[] = {
{/* zName: */ "wal_checkpoint",
/* ePragTyp: */ PragTyp_WAL_CHECKPOINT,
/* ePragFlg: */ PragFlg_NeedSchema,
- /* ColNames: */ 44, 3,
+ /* ColNames: */ 50, 3,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
@@ -131080,7 +137119,7 @@ static const PragmaName aPragmaName[] = {
/* iArg: */ SQLITE_WriteSchema|SQLITE_NoSchemaError },
#endif
};
-/* Number of pragmas: 67 on by default, 77 total. */
+/* Number of pragmas: 68 on by default, 78 total. */
/************** End of pragma.h **********************************************/
/************** Continuing where we left off in pragma.c *********************/
@@ -131362,15 +137401,16 @@ static void pragmaFunclistLine(
int isBuiltin, /* True if this is a built-in function */
int showInternFuncs /* True if showing internal functions */
){
+ u32 mask =
+ SQLITE_DETERMINISTIC |
+ SQLITE_DIRECTONLY |
+ SQLITE_SUBTYPE |
+ SQLITE_INNOCUOUS |
+ SQLITE_FUNC_INTERNAL
+ ;
+ if( showInternFuncs ) mask = 0xffffffff;
for(; p; p=p->pNext){
const char *zType;
- static const u32 mask =
- SQLITE_DETERMINISTIC |
- SQLITE_DIRECTONLY |
- SQLITE_SUBTYPE |
- SQLITE_INNOCUOUS |
- SQLITE_FUNC_INTERNAL
- ;
static const char *azEnc[] = { 0, "utf8", "utf16le", "utf16be" };
assert( SQLITE_FUNC_ENCMASK==0x3 );
@@ -131537,7 +137577,11 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Pragma(
/* Locate the pragma in the lookup table */
pPragma = pragmaLocate(zLeft);
- if( pPragma==0 ) goto pragma_out;
+ if( pPragma==0 ){
+ /* IMP: R-43042-22504 No error messages are generated if an
+ ** unknown pragma is issued. */
+ goto pragma_out;
+ }
/* Make sure the database schema is loaded if the pragma requires that */
if( (pPragma->mPragFlg & PragFlg_NeedSchema)!=0 ){
@@ -131873,7 +137917,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Pragma(
*/
#ifndef SQLITE_OMIT_AUTOVACUUM
case PragTyp_INCREMENTAL_VACUUM: {
- int iLimit, addr;
+ int iLimit = 0, addr;
if( zRight==0 || !sqlcipher_sqlite3GetInt32(zRight, &iLimit) || iLimit<=0 ){
iLimit = 0x7fffffff;
}
@@ -132030,6 +138074,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Pragma(
**
*/
case PragTyp_TEMP_STORE_DIRECTORY: {
+ sqlcipher_sqlite3_mutex_enter(sqlcipher_sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
if( !zRight ){
returnSingleText(v, sqlcipher_sqlite3_temp_directory);
}else{
@@ -132039,6 +138084,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Pragma(
rc = sqlcipher_sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res);
if( rc!=SQLITE_OK || res==0 ){
sqlcipher_sqlite3ErrorMsg(pParse, "not a writable directory");
+ sqlcipher_sqlite3_mutex_leave(sqlcipher_sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
goto pragma_out;
}
}
@@ -132056,6 +138102,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Pragma(
}
#endif /* SQLITE_OMIT_WSD */
}
+ sqlcipher_sqlite3_mutex_leave(sqlcipher_sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
break;
}
@@ -132074,6 +138121,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Pragma(
**
*/
case PragTyp_DATA_STORE_DIRECTORY: {
+ sqlcipher_sqlite3_mutex_enter(sqlcipher_sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
if( !zRight ){
returnSingleText(v, sqlcipher_sqlite3_data_directory);
}else{
@@ -132083,6 +138131,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Pragma(
rc = sqlcipher_sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res);
if( rc!=SQLITE_OK || res==0 ){
sqlcipher_sqlite3ErrorMsg(pParse, "not a writable directory");
+ sqlcipher_sqlite3_mutex_leave(sqlcipher_sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
goto pragma_out;
}
}
@@ -132094,6 +138143,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Pragma(
}
#endif /* SQLITE_OMIT_WSD */
}
+ sqlcipher_sqlite3_mutex_leave(sqlcipher_sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
break;
}
#endif
@@ -132187,6 +138237,14 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Pragma(
}else{
db->flags &= ~mask;
if( mask==SQLITE_DeferFKs ) db->nDeferredImmCons = 0;
+ if( (mask & SQLITE_WriteSchema)!=0
+ && sqlcipher_sqlite3_stricmp(zRight, "reset")==0
+ ){
+ /* IMP: R-60817-01178 If the argument is "RESET" then schema
+ ** writing is disabled (as with "PRAGMA writable_schema=OFF") and,
+ ** in addition, the schema is reloaded. */
+ sqlcipher_sqlite3ResetAllSchemasOfConnection(db);
+ }
}
/* Many of the flag-pragmas modify the code generated by the SQL
@@ -132227,6 +138285,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Pragma(
sqlcipher_sqlite3ViewGetColumnNames(pParse, pTab);
for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
int isHidden = 0;
+ const Expr *pColExpr;
if( pCol->colFlags & COLFLAG_NOINSERT ){
if( pPragma->iArg==0 ){
nHidden++;
@@ -132247,13 +138306,16 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Pragma(
}else{
for(k=1; k<=pTab->nCol && pPk->aiColumn[k-1]!=i; k++){}
}
- assert( pCol->pDflt==0 || pCol->pDflt->op==TK_SPAN || isHidden>=2 );
+ pColExpr = sqlcipher_sqlite3ColumnExpr(pTab,pCol);
+ assert( pColExpr==0 || pColExpr->op==TK_SPAN || isHidden>=2 );
+ assert( pColExpr==0 || !ExprHasProperty(pColExpr, EP_IntValue)
+ || isHidden>=2 );
sqlcipher_sqlite3VdbeMultiLoad(v, 1, pPragma->iArg ? "issisii" : "issisi",
i-nHidden,
- pCol->zName,
+ pCol->zCnName,
sqlcipher_sqlite3ColumnType(pCol,""),
pCol->notNull ? 1 : 0,
- pCol->pDflt && isHidden<2 ? pCol->pDflt->u.zToken : 0,
+ (isHidden>=2 || pColExpr==0) ? 0 : pColExpr->u.zToken,
k,
isHidden);
}
@@ -132261,6 +138323,85 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Pragma(
}
break;
+ /*
+ ** PRAGMA table_list
+ **
+ ** Return a single row for each table, virtual table, or view in the
+ ** entire schema.
+ **
+ ** schema: Name of attached database hold this table
+ ** name: Name of the table itself
+ ** type: "table", "view", "virtual", "shadow"
+ ** ncol: Number of columns
+ ** wr: True for a WITHOUT ROWID table
+ ** strict: True for a STRICT table
+ */
+ case PragTyp_TABLE_LIST: {
+ int ii;
+ pParse->nMem = 6;
+ sqlcipher_sqlite3CodeVerifyNamedSchema(pParse, zDb);
+ for(ii=0; ii<db->nDb; ii++){
+ HashElem *k;
+ Hash *pHash;
+ int initNCol;
+ if( zDb && sqlcipher_sqlite3_stricmp(zDb, db->aDb[ii].zDbSName)!=0 ) continue;
+
+ /* Ensure that the Table.nCol field is initialized for all views
+ ** and virtual tables. Each time we initialize a Table.nCol value
+ ** for a table, that can potentially disrupt the hash table, so restart
+ ** the initialization scan.
+ */
+ pHash = &db->aDb[ii].pSchema->tblHash;
+ initNCol = sqliteHashCount(pHash);
+ while( initNCol-- ){
+ for(k=sqliteHashFirst(pHash); 1; k=sqliteHashNext(k) ){
+ Table *pTab;
+ if( k==0 ){ initNCol = 0; break; }
+ pTab = sqliteHashData(k);
+ if( pTab->nCol==0 ){
+ char *zSql = sqlcipher_sqlite3MPrintf(db, "SELECT*FROM\"%w\"", pTab->zName);
+ if( zSql ){
+ sqlcipher_sqlite3_stmt *pDummy = 0;
+ (void)sqlcipher_sqlite3_prepare(db, zSql, -1, &pDummy, 0);
+ (void)sqlcipher_sqlite3_finalize(pDummy);
+ sqlcipher_sqlite3DbFree(db, zSql);
+ }
+ if( db->mallocFailed ){
+ sqlcipher_sqlite3ErrorMsg(db->pParse, "out of memory");
+ db->pParse->rc = SQLITE_NOMEM_BKPT;
+ }
+ pHash = &db->aDb[ii].pSchema->tblHash;
+ break;
+ }
+ }
+ }
+
+ for(k=sqliteHashFirst(pHash); k; k=sqliteHashNext(k) ){
+ Table *pTab = sqliteHashData(k);
+ const char *zType;
+ if( zRight && sqlcipher_sqlite3_stricmp(zRight, pTab->zName)!=0 ) continue;
+ if( IsView(pTab) ){
+ zType = "view";
+ }else if( IsVirtual(pTab) ){
+ zType = "virtual";
+ }else if( pTab->tabFlags & TF_Shadow ){
+ zType = "shadow";
+ }else{
+ zType = "table";
+ }
+ sqlcipher_sqlite3VdbeMultiLoad(v, 1, "sssiii",
+ db->aDb[ii].zDbSName,
+ sqlcipher_sqlite3PreferredTableName(pTab->zName),
+ zType,
+ pTab->nCol,
+ (pTab->tabFlags & TF_WithoutRowid)!=0,
+ (pTab->tabFlags & TF_Strict)!=0
+ );
+ }
+ }
+ }
+ break;
+
#ifdef SQLITE_DEBUG
case PragTyp_STATS: {
Index *pIdx;
@@ -132270,7 +138411,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Pragma(
for(i=sqliteHashFirst(&pDb->pSchema->tblHash); i; i=sqliteHashNext(i)){
Table *pTab = sqliteHashData(i);
sqlcipher_sqlite3VdbeMultiLoad(v, 1, "ssiii",
- pTab->zName,
+ sqlcipher_sqlite3PreferredTableName(pTab->zName),
0,
pTab->szTabRow,
pTab->nRowLogEst,
@@ -132320,7 +138461,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Pragma(
for(i=0; i<mx; i++){
i16 cnum = pIdx->aiColumn[i];
sqlcipher_sqlite3VdbeMultiLoad(v, 1, "iisX", i, cnum,
- cnum<0 ? 0 : pTab->aCol[cnum].zName);
+ cnum<0 ? 0 : pTab->aCol[cnum].zCnName);
if( pPragma->iArg ){
sqlcipher_sqlite3VdbeMultiLoad(v, 4, "isiX",
pIdx->aSortOrder[i],
@@ -132389,11 +138530,13 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Pragma(
pParse->nMem = 6;
for(i=0; i<SQLITE_FUNC_HASH_SZ; i++){
for(p=sqlcipher_sqlite3BuiltinFunctions.a[i]; p; p=p->u.pHash ){
+ assert( p->funcFlags & SQLITE_FUNC_BUILTIN );
pragmaFunclistLine(v, p, 1, showInternFunc);
}
}
for(j=sqliteHashFirst(&db->aFunc); j; j=sqliteHashNext(j)){
p = (FuncDef*)sqliteHashData(j);
+ assert( (p->funcFlags & SQLITE_FUNC_BUILTIN)==0 );
pragmaFunclistLine(v, p, 0, showInternFunc);
}
}
@@ -132427,8 +138570,8 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Pragma(
FKey *pFK;
Table *pTab;
pTab = sqlcipher_sqlite3FindTable(db, zRight, zDb);
- if( pTab ){
- pFK = pTab->pFKey;
+ if( pTab && IsOrdinaryTable(pTab) ){
+ pFK = pTab->u.tab.pFKey;
if( pFK ){
int iTabDb = sqlcipher_sqlite3SchemaToIndex(db, pTab->pSchema);
int i = 0;
@@ -132441,7 +138584,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Pragma(
i,
j,
pFK->zTo,
- pTab->aCol[pFK->aCol[j].iFrom].zName,
+ pTab->aCol[pFK->aCol[j].iFrom].zCnName,
pFK->aCol[j].zCol,
actionName(pFK->aAction[1]), /* ON UPDATE */
actionName(pFK->aAction[0]), /* ON DELETE */
@@ -132468,7 +138611,6 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Pragma(
HashElem *k; /* Loop counter: Next table in schema */
int x; /* result variable */
int regResult; /* 3 registers to hold a result row */
- int regKey; /* Register to hold key for checking the FK */
int regRow; /* Registers to hold a row from pTab */
int addrTop; /* Top of a loop checking foreign keys */
int addrOk; /* Jump here if the key is OK */
@@ -132476,7 +138618,6 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Pragma(
regResult = pParse->nMem+1;
pParse->nMem += 4;
- regKey = ++pParse->nMem;
regRow = ++pParse->nMem;
k = sqliteHashFirst(&db->aDb[iDb].pSchema->tblHash);
while( k ){
@@ -132487,7 +138628,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Pragma(
pTab = (Table*)sqliteHashData(k);
k = sqliteHashNext(k);
}
- if( pTab==0 || pTab->pFKey==0 ) continue;
+ if( pTab==0 || !IsOrdinaryTable(pTab) || pTab->u.tab.pFKey==0 ) continue;
iDb = sqlcipher_sqlite3SchemaToIndex(db, pTab->pSchema);
zDb = db->aDb[iDb].zDbSName;
sqlcipher_sqlite3CodeVerifySchema(pParse, iDb);
@@ -132495,7 +138636,8 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Pragma(
if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow;
sqlcipher_sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead);
sqlcipher_sqlite3VdbeLoadString(v, regResult, pTab->zName);
- for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
+ assert( IsOrdinaryTable(pTab) );
+ for(i=1, pFK=pTab->u.tab.pFKey; pFK; i++, pFK=pFK->pNextFrom){
pParent = sqlcipher_sqlite3FindTable(db, pFK->zTo, zDb);
if( pParent==0 ) continue;
pIdx = 0;
@@ -132517,7 +138659,8 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Pragma(
if( pFK ) break;
if( pParse->nTab<i ) pParse->nTab = i;
addrTop = sqlcipher_sqlite3VdbeAddOp1(v, OP_Rewind, 0); VdbeCoverage(v);
- for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
+ assert( IsOrdinaryTable(pTab) );
+ for(i=1, pFK=pTab->u.tab.pFKey; pFK; i++, pFK=pFK->pNextFrom){
pParent = sqlcipher_sqlite3FindTable(db, pFK->zTo, zDb);
pIdx = 0;
aiCols = 0;
@@ -132531,6 +138674,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Pragma(
** regRow..regRow+n. If any of the child key values are NULL, this
** row cannot cause an FK violation. Jump directly to addrOk in
** this case. */
+ if( regRow+pFK->nCol>pParse->nMem ) pParse->nMem = regRow+pFK->nCol;
for(j=0; j<pFK->nCol; j++){
int iCol = aiCols ? aiCols[j] : pFK->aCol[j].iFrom;
sqlcipher_sqlite3ExprCodeGetColumnOfTable(v, pTab, 0, iCol, regRow+j);
@@ -132540,9 +138684,9 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Pragma(
/* Generate code to query the parent index for a matching parent
** key. If a match is found, jump to addrOk. */
if( pIdx ){
- sqlcipher_sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, pFK->nCol, regKey,
+ sqlcipher_sqlite3VdbeAddOp4(v, OP_Affinity, regRow, pFK->nCol, 0,
sqlcipher_sqlite3IndexAffinityStr(db,pIdx), pFK->nCol);
- sqlcipher_sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0);
+ sqlcipher_sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regRow, pFK->nCol);
VdbeCoverage(v);
}else if( pParent ){
int jmp = sqlcipher_sqlite3VdbeCurrentAddr(v)+2;
@@ -132717,8 +138861,9 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Pragma(
int loopTop;
int iDataCur, iIdxCur;
int r1 = -1;
+ int bStrict;
- if( pTab->tnum<1 ) continue; /* Skip VIEWs or VIRTUAL TABLEs */
+ if( !IsOrdinaryTable(pTab) ) continue;
if( pObjTab && pObjTab!=pTab ) continue;
pPk = HasRowid(pTab) ? 0 : sqlcipher_sqlite3PrimaryKeyIndex(pTab);
sqlcipher_sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead, 0,
@@ -132738,23 +138883,48 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Pragma(
/* Sanity check on record header decoding */
sqlcipher_sqlite3VdbeAddOp3(v, OP_Column, iDataCur, pTab->nNVCol-1,3);
sqlcipher_sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
+ VdbeComment((v, "(right-most column)"));
}
- /* Verify that all NOT NULL columns really are NOT NULL */
+ /* Verify that all NOT NULL columns really are NOT NULL. At the
+ ** same time verify the type of the content of STRICT tables */
+ bStrict = (pTab->tabFlags & TF_Strict)!=0;
for(j=0; j<pTab->nCol; j++){
char *zErr;
- int jmp2;
+ Column *pCol = pTab->aCol + j;
+ int doError, jmp2;
if( j==pTab->iPKey ) continue;
- if( pTab->aCol[j].notNull==0 ) continue;
+ if( pCol->notNull==0 && !bStrict ) continue;
+ doError = bStrict ? sqlcipher_sqlite3VdbeMakeLabel(pParse) : 0;
sqlcipher_sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3);
if( sqlcipher_sqlite3VdbeGetOp(v,-1)->opcode==OP_Column ){
sqlcipher_sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
}
- jmp2 = sqlcipher_sqlite3VdbeAddOp1(v, OP_NotNull, 3); VdbeCoverage(v);
- zErr = sqlcipher_sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName,
- pTab->aCol[j].zName);
- sqlcipher_sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
- integrityCheckResultRow(v);
- sqlcipher_sqlite3VdbeJumpHere(v, jmp2);
+ if( pCol->notNull ){
+ jmp2 = sqlcipher_sqlite3VdbeAddOp1(v, OP_NotNull, 3); VdbeCoverage(v);
+ zErr = sqlcipher_sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName,
+ pCol->zCnName);
+ sqlcipher_sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
+ if( bStrict && pCol->eCType!=COLTYPE_ANY ){
+ sqlcipher_sqlite3VdbeGoto(v, doError);
+ }else{
+ integrityCheckResultRow(v);
+ }
+ sqlcipher_sqlite3VdbeJumpHere(v, jmp2);
+ }
+ if( (pTab->tabFlags & TF_Strict)!=0
+ && pCol->eCType!=COLTYPE_ANY
+ ){
+ jmp2 = sqlcipher_sqlite3VdbeAddOp3(v, OP_IsNullOrType, 3, 0,
+ sqlcipher_sqlite3StdTypeMap[pCol->eCType-1]);
+ VdbeCoverage(v);
+ zErr = sqlcipher_sqlite3MPrintf(db, "non-%s value in %s.%s",
+ sqlcipher_sqlite3StdType[pCol->eCType-1],
+ pTab->zName, pTab->aCol[j].zCnName);
+ sqlcipher_sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
+ sqlcipher_sqlite3VdbeResolveLabel(v, doError);
+ integrityCheckResultRow(v);
+ sqlcipher_sqlite3VdbeJumpHere(v, jmp2);
+ }
}
/* Verify CHECK constraints */
if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){
@@ -133039,7 +139209,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Pragma(
** Checkpoint the database.
*/
case PragTyp_WAL_CHECKPOINT: {
- int iBt = (pId2->z?iDb:SQLITE_MAX_ATTACHED);
+ int iBt = (pId2->z?iDb:SQLITE_MAX_DB);
int eMode = SQLITE_CHECKPOINT_PASSIVE;
if( zRight ){
if( sqlcipher_sqlite3StrICmp(zRight, "full")==0 ){
@@ -133288,12 +139458,12 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Pragma(
case PragTyp_ANALYSIS_LIMIT: {
sqlcipher_sqlite3_int64 N;
if( zRight
- && sqlcipher_sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK
+ && sqlcipher_sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK /* IMP: R-40975-20399 */
&& N>=0
){
db->nAnalysisLimit = (int)(N&0x7fffffff);
}
- returnSingleInt(v, db->nAnalysisLimit);
+ returnSingleInt(v, db->nAnalysisLimit); /* IMP: R-57594-65522 */
break;
}
@@ -133730,7 +139900,7 @@ SQLITE_PRIVATE Module *sqlcipher_sqlite3PragmaVtabRegister(sqlcipher_sqlite3 *db
*/
static void corruptSchema(
InitData *pData, /* Initialization context */
- const char *zObj, /* Object being parsed at the point of error */
+ char **azObj, /* Type and name of object being parsed */
const char *zExtra /* Error information */
){
sqlcipher_sqlite3 *db = pData->db;
@@ -133738,14 +139908,23 @@ static void corruptSchema(
pData->rc = SQLITE_NOMEM_BKPT;
}else if( pData->pzErrMsg[0]!=0 ){
/* A error message has already been generated. Do not overwrite it */
- }else if( pData->mInitFlags & INITFLAG_AlterTable ){
- *pData->pzErrMsg = sqlcipher_sqlite3DbStrDup(db, zExtra);
+ }else if( pData->mInitFlags & (INITFLAG_AlterMask) ){
+ static const char *azAlterType[] = {
+ "rename",
+ "drop column",
+ "add column"
+ };
+ *pData->pzErrMsg = sqlcipher_sqlite3MPrintf(db,
+ "error in %s %s after %s: %s", azObj[0], azObj[1],
+ azAlterType[(pData->mInitFlags&INITFLAG_AlterMask)-1],
+ zExtra
+ );
pData->rc = SQLITE_ERROR;
}else if( db->flags & SQLITE_WriteSchema ){
pData->rc = SQLITE_CORRUPT_BKPT;
}else{
char *z;
- if( zObj==0 ) zObj = "?";
+ const char *zObj = azObj[1] ? azObj[1] : "?";
z = sqlcipher_sqlite3MPrintf(db, "malformed database schema (%s)", zObj);
if( zExtra && zExtra[0] ) z = sqlcipher_sqlite3MPrintf(db, "%z - %s", z, zExtra);
*pData->pzErrMsg = z;
@@ -133801,21 +139980,28 @@ SQLITE_PRIVATE int sqlcipher_sqlite3InitCallback(void *pInit, int argc, char **a
UNUSED_PARAMETER2(NotUsed, argc);
assert( sqlcipher_sqlite3_mutex_held(db->mutex) );
db->mDbFlags |= DBFLAG_EncodingFixed;
+ if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */
pData->nInitRow++;
if( db->mallocFailed ){
- corruptSchema(pData, argv[1], 0);
+ corruptSchema(pData, argv, 0);
return 1;
}
assert( iDb>=0 && iDb<db->nDb );
- if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */
if( argv[3]==0 ){
- corruptSchema(pData, argv[1], 0);
- }else if( sqlcipher_sqlite3_strnicmp(argv[4],"create ",7)==0 ){
+ corruptSchema(pData, argv, 0);
+ }else if( argv[4]
+ && 'c'==sqlcipher_sqlite3UpperToLower[(unsigned char)argv[4][0]]
+ && 'r'==sqlcipher_sqlite3UpperToLower[(unsigned char)argv[4][1]] ){
/* Call the parser to process a CREATE TABLE, INDEX or VIEW.
** But because db->init.busy is set to 1, no VDBE code is generated
** or executed. All the parser does is build the internal data
** structures that describe the table, index, or view.
+ **
+ ** No other valid SQL statement, other than the variable CREATE statements,
+ ** can begin with the letters "C" and "R". Thus, it is not possible run
+ ** any other kind of statement while parsing the schema, even a corrupt
+ ** schema.
*/
int rc;
u8 saved_iDb = db->init.iDb;
@@ -133828,11 +140014,11 @@ SQLITE_PRIVATE int sqlcipher_sqlite3InitCallback(void *pInit, int argc, char **a
|| (db->init.newTnum>pData->mxPage && pData->mxPage>0)
){
if( sqlcipher_sqlite3Config.bExtraSchemaChecks ){
- corruptSchema(pData, argv[1], "invalid rootpage");
+ corruptSchema(pData, argv, "invalid rootpage");
}
}
db->init.orphanTrigger = 0;
- db->init.azInit = argv;
+ db->init.azInit = (const char**)argv;
pStmt = 0;
TESTONLY(rcp = ) sqlcipher_sqlite3Prepare(db, argv[4], -1, 0, 0, &pStmt, 0);
rc = db->errCode;
@@ -133847,13 +140033,14 @@ SQLITE_PRIVATE int sqlcipher_sqlite3InitCallback(void *pInit, int argc, char **a
if( rc==SQLITE_NOMEM ){
sqlcipher_sqlite3OomFault(db);
}else if( rc!=SQLITE_INTERRUPT && (rc&0xFF)!=SQLITE_LOCKED ){
- corruptSchema(pData, argv[1], sqlcipher_sqlite3_errmsg(db));
+ corruptSchema(pData, argv, sqlcipher_sqlite3_errmsg(db));
}
}
}
+ db->init.azInit = sqlcipher_sqlite3StdType; /* Any array of string ptrs will do */
sqlcipher_sqlite3_finalize(pStmt);
}else if( argv[1]==0 || (argv[4]!=0 && argv[4][0]!=0) ){
- corruptSchema(pData, argv[1], 0);
+ corruptSchema(pData, argv, 0);
}else{
/* If the SQL column is blank it means this is an index that
** was created to be the PRIMARY KEY or to fulfill a UNIQUE
@@ -133864,7 +140051,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3InitCallback(void *pInit, int argc, char **a
Index *pIndex;
pIndex = sqlcipher_sqlite3FindIndex(db, argv[1], db->aDb[iDb].zDbSName);
if( pIndex==0 ){
- corruptSchema(pData, argv[1], "orphan index");
+ corruptSchema(pData, argv, "orphan index");
}else
if( sqlcipher_sqlite3GetUInt32(argv[3],&pIndex->tnum)==0
|| pIndex->tnum<2
@@ -133872,7 +140059,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3InitCallback(void *pInit, int argc, char **a
|| sqlcipher_sqlite3IndexHasDuplicateRootPage(pIndex)
){
if( sqlcipher_sqlite3Config.bExtraSchemaChecks ){
- corruptSchema(pData, argv[1], "invalid rootpage");
+ corruptSchema(pData, argv, "invalid rootpage");
}
}
}
@@ -134075,18 +140262,22 @@ SQLITE_PRIVATE int sqlcipher_sqlite3InitOne(sqlcipher_sqlite3 *db, int iDb, char
}
#endif
}
+ assert( pDb == &(db->aDb[iDb]) );
if( db->mallocFailed ){
rc = SQLITE_NOMEM_BKPT;
sqlcipher_sqlite3ResetAllSchemasOfConnection(db);
- }
- if( rc==SQLITE_OK || (db->flags&SQLITE_NoSchemaError)){
- /* Black magic: If the SQLITE_NoSchemaError flag is set, then consider
- ** the schema loaded, even if errors occurred. In this situation the
- ** current sqlcipher_sqlite3_prepare() operation will fail, but the following one
- ** will attempt to compile the supplied statement against whatever subset
- ** of the schema was loaded before the error occurred. The primary
- ** purpose of this is to allow access to the sqlite_schema table
- ** even when its contents have been corrupted.
+ pDb = &db->aDb[iDb];
+ }else
+ if( rc==SQLITE_OK || ((db->flags&SQLITE_NoSchemaError) && rc!=SQLITE_NOMEM)){
+ /* Hack: If the SQLITE_NoSchemaError flag is set, then consider
+ ** the schema loaded, even if errors (other than OOM) occurred. In
+ ** this situation the current sqlcipher_sqlite3_prepare() operation will fail,
+ ** but the following one will attempt to compile the supplied statement
+ ** against whatever subset of the schema was loaded before the error
+ ** occurred.
+ **
+ ** The primary purpose of this is to allow access to the sqlite_schema
+ ** table even when its contents have been corrupted.
*/
DbSetProperty(db, iDb, DB_SchemaLoaded);
rc = SQLITE_OK;
@@ -134196,6 +140387,7 @@ static void schemaIsValid(Parse *pParse){
rc = sqlcipher_sqlite3BtreeBeginTrans(pBt, 0, 0);
if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
sqlcipher_sqlite3OomFault(db);
+ pParse->rc = SQLITE_NOMEM;
}
if( rc!=SQLITE_OK ) return;
openedTransaction = 1;
@@ -134253,36 +140445,112 @@ SQLITE_PRIVATE int sqlcipher_sqlite3SchemaToIndex(sqlcipher_sqlite3 *db, Schema
}
/*
-** Deallocate a single AggInfo object
-*/
-static void agginfoFree(sqlcipher_sqlite3 *db, AggInfo *p){
- sqlcipher_sqlite3DbFree(db, p->aCol);
- sqlcipher_sqlite3DbFree(db, p->aFunc);
- sqlcipher_sqlite3DbFree(db, p);
-}
-
-/*
** Free all memory allocations in the pParse object
*/
-SQLITE_PRIVATE void sqlcipher_sqlite3ParserReset(Parse *pParse){
+SQLITE_PRIVATE void sqlcipher_sqlite3ParseObjectReset(Parse *pParse){
sqlcipher_sqlite3 *db = pParse->db;
- AggInfo *pThis = pParse->pAggList;
- while( pThis ){
- AggInfo *pNext = pThis->pNext;
- agginfoFree(db, pThis);
- pThis = pNext;
+ assert( db!=0 );
+ assert( db->pParse==pParse );
+ assert( pParse->nested==0 );
+#ifndef SQLITE_OMIT_SHARED_CACHE
+ sqlcipher_sqlite3DbFree(db, pParse->aTableLock);
+#endif
+ while( pParse->pCleanup ){
+ ParseCleanup *pCleanup = pParse->pCleanup;
+ pParse->pCleanup = pCleanup->pNext;
+ pCleanup->xCleanup(db, pCleanup->pPtr);
+ sqlcipher_sqlite3DbFreeNN(db, pCleanup);
}
sqlcipher_sqlite3DbFree(db, pParse->aLabel);
- sqlcipher_sqlite3ExprListDelete(db, pParse->pConstExpr);
- if( db ){
- assert( db->lookaside.bDisable >= pParse->disableLookaside );
- db->lookaside.bDisable -= pParse->disableLookaside;
- db->lookaside.sz = db->lookaside.bDisable ? 0 : db->lookaside.szTrue;
- }
+ if( pParse->pConstExpr ){
+ sqlcipher_sqlite3ExprListDelete(db, pParse->pConstExpr);
+ }
+ assert( db->lookaside.bDisable >= pParse->disableLookaside );
+ db->lookaside.bDisable -= pParse->disableLookaside;
+ db->lookaside.sz = db->lookaside.bDisable ? 0 : db->lookaside.szTrue;
+ assert( pParse->db->pParse==pParse );
+ db->pParse = pParse->pOuterParse;
+ pParse->db = 0;
pParse->disableLookaside = 0;
}
/*
+** Add a new cleanup operation to a Parser. The cleanup should happen when
+** the parser object is destroyed. But, beware: the cleanup might happen
+** immediately.
+**
+** Use this mechanism for uncommon cleanups. There is a higher setup
+** cost for this mechansim (an extra malloc), so it should not be used
+** for common cleanups that happen on most calls. But for less
+** common cleanups, we save a single NULL-pointer comparison in
+** sqlcipher_sqlite3ParseObjectReset(), which reduces the total CPU cycle count.
+**
+** If a memory allocation error occurs, then the cleanup happens immediately.
+** When either SQLITE_DEBUG or SQLITE_COVERAGE_TEST are defined, the
+** pParse->earlyCleanup flag is set in that case. Calling code show verify
+** that test cases exist for which this happens, to guard against possible
+** use-after-free errors following an OOM. The preferred way to do this is
+** to immediately follow the call to this routine with:
+**
+** testcase( pParse->earlyCleanup );
+**
+** This routine returns a copy of its pPtr input (the third parameter)
+** except if an early cleanup occurs, in which case it returns NULL. So
+** another way to check for early cleanup is to check the return value.
+** Or, stop using the pPtr parameter with this call and use only its
+** return value thereafter. Something like this:
+**
+** pObj = sqlcipher_sqlite3ParserAddCleanup(pParse, destructor, pObj);
+*/
+SQLITE_PRIVATE void *sqlcipher_sqlite3ParserAddCleanup(
+ Parse *pParse, /* Destroy when this Parser finishes */
+ void (*xCleanup)(sqlcipher_sqlite3*,void*), /* The cleanup routine */
+ void *pPtr /* Pointer to object to be cleaned up */
+){
+ ParseCleanup *pCleanup = sqlcipher_sqlite3DbMallocRaw(pParse->db, sizeof(*pCleanup));
+ if( pCleanup ){
+ pCleanup->pNext = pParse->pCleanup;
+ pParse->pCleanup = pCleanup;
+ pCleanup->pPtr = pPtr;
+ pCleanup->xCleanup = xCleanup;
+ }else{
+ xCleanup(pParse->db, pPtr);
+ pPtr = 0;
+#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
+ pParse->earlyCleanup = 1;
+#endif
+ }
+ return pPtr;
+}
+
+/*
+** Turn bulk memory into a valid Parse object and link that Parse object
+** into database connection db.
+**
+** Call sqlcipher_sqlite3ParseObjectReset() to undo this operation.
+**
+** Caution: Do not confuse this routine with sqlcipher_sqlite3ParseObjectInit() which
+** is generated by Lemon.
+*/
+SQLITE_PRIVATE void sqlcipher_sqlite3ParseObjectInit(Parse *pParse, sqlcipher_sqlite3 *db){
+ memset(PARSE_HDR(pParse), 0, PARSE_HDR_SZ);
+ memset(PARSE_TAIL(pParse), 0, PARSE_TAIL_SZ);
+ assert( db->pParse!=pParse );
+ pParse->pOuterParse = db->pParse;
+ db->pParse = pParse;
+ pParse->db = db;
+ if( db->mallocFailed ) sqlcipher_sqlite3ErrorMsg(pParse, "out of memory");
+}
+
+/*
+** Maximum number of times that we will try again to prepare a statement
+** that returns SQLITE_ERROR_RETRY.
+*/
+#ifndef SQLITE_MAX_PREPARE_RETRY
+# define SQLITE_MAX_PREPARE_RETRY 25
+#endif
+
+/*
** Compile the UTF-8 encoded SQL statement zSql into a statement handle.
*/
static int sqlcipher_sqlite3Prepare(
@@ -134294,16 +140562,19 @@ static int sqlcipher_sqlite3Prepare(
sqlcipher_sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
const char **pzTail /* OUT: End of parsed string */
){
- char *zErrMsg = 0; /* Error message */
int rc = SQLITE_OK; /* Result code */
int i; /* Loop counter */
Parse sParse; /* Parsing context */
- memset(&sParse, 0, PARSE_HDR_SZ);
+ /* sqlcipher_sqlite3ParseObjectInit(&sParse, db); // inlined for performance */
+ memset(PARSE_HDR(&sParse), 0, PARSE_HDR_SZ);
memset(PARSE_TAIL(&sParse), 0, PARSE_TAIL_SZ);
+ sParse.pOuterParse = db->pParse;
+ db->pParse = &sParse;
+ sParse.db = db;
sParse.pReprepare = pReprepare;
assert( ppStmt && *ppStmt==0 );
- /* assert( !db->mallocFailed ); // not true with SQLITE_USE_ALLOCA */
+ if( db->mallocFailed ) sqlcipher_sqlite3ErrorMsg(&sParse, "out of memory");
assert( sqlcipher_sqlite3_mutex_held(db->mutex) );
/* For a long-term use prepared statement avoid the use of
@@ -134356,7 +140627,6 @@ static int sqlcipher_sqlite3Prepare(
sqlcipher_sqlite3VtabUnlockList(db);
- sParse.db = db;
if( nBytes>=0 && (nBytes==0 || zSql[nBytes-1]!=0) ){
char *zSqlCopy;
int mxLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
@@ -134369,23 +140639,17 @@ static int sqlcipher_sqlite3Prepare(
}
zSqlCopy = sqlcipher_sqlite3DbStrNDup(db, zSql, nBytes);
if( zSqlCopy ){
- sqlcipher_sqlite3RunParser(&sParse, zSqlCopy, &zErrMsg);
+ sqlcipher_sqlite3RunParser(&sParse, zSqlCopy);
sParse.zTail = &zSql[sParse.zTail-zSqlCopy];
sqlcipher_sqlite3DbFree(db, zSqlCopy);
}else{
sParse.zTail = &zSql[nBytes];
}
}else{
- sqlcipher_sqlite3RunParser(&sParse, zSql, &zErrMsg);
+ sqlcipher_sqlite3RunParser(&sParse, zSql);
}
assert( 0==sParse.nQueryLoop );
- if( sParse.rc==SQLITE_DONE ){
- sParse.rc = SQLITE_OK;
- }
- if( sParse.checkSchema ){
- schemaIsValid(&sParse);
- }
if( pzTail ){
*pzTail = sParse.zTail;
}
@@ -134395,21 +140659,30 @@ static int sqlcipher_sqlite3Prepare(
}
if( db->mallocFailed ){
sParse.rc = SQLITE_NOMEM_BKPT;
+ sParse.checkSchema = 0;
}
- rc = sParse.rc;
- if( rc!=SQLITE_OK ){
- if( sParse.pVdbe ) sqlcipher_sqlite3VdbeFinalize(sParse.pVdbe);
- assert(!(*ppStmt));
+ if( sParse.rc!=SQLITE_OK && sParse.rc!=SQLITE_DONE ){
+ if( sParse.checkSchema && db->init.busy==0 ){
+ schemaIsValid(&sParse);
+ }
+ if( sParse.pVdbe ){
+ sqlcipher_sqlite3VdbeFinalize(sParse.pVdbe);
+ }
+ assert( 0==(*ppStmt) );
+ rc = sParse.rc;
+ if( sParse.zErrMsg ){
+ sqlcipher_sqlite3ErrorWithMsg(db, rc, "%s", sParse.zErrMsg);
+ sqlcipher_sqlite3DbFree(db, sParse.zErrMsg);
+ }else{
+ sqlcipher_sqlite3Error(db, rc);
+ }
}else{
+ assert( sParse.zErrMsg==0 );
*ppStmt = (sqlcipher_sqlite3_stmt*)sParse.pVdbe;
+ rc = SQLITE_OK;
+ sqlcipher_sqlite3ErrorClear(db);
}
- if( zErrMsg ){
- sqlcipher_sqlite3ErrorWithMsg(db, rc, "%s", zErrMsg);
- sqlcipher_sqlite3DbFree(db, zErrMsg);
- }else{
- sqlcipher_sqlite3Error(db, rc);
- }
/* Delete any TriggerPrg structures allocated while parsing this statement. */
while( sParse.pTriggerPrg ){
@@ -134420,7 +140693,7 @@ static int sqlcipher_sqlite3Prepare(
end_prepare:
- sqlcipher_sqlite3ParserReset(&sParse);
+ sqlcipher_sqlite3ParseObjectReset(&sParse);
return rc;
}
static int sqlcipher_sqlite3LockAndPrepare(
@@ -134450,7 +140723,8 @@ static int sqlcipher_sqlite3LockAndPrepare(
** reset is considered a permanent error. */
rc = sqlcipher_sqlite3Prepare(db, zSql, nBytes, prepFlags, pOld, ppStmt, pzTail);
assert( rc==SQLITE_OK || *ppStmt==0 );
- }while( rc==SQLITE_ERROR_RETRY
+ if( rc==SQLITE_OK || db->mallocFailed ) break;
+ }while( (rc==SQLITE_ERROR_RETRY && (cnt++)<SQLITE_MAX_PREPARE_RETRY)
|| (rc==SQLITE_SCHEMA && (sqlcipher_sqlite3ResetOneSchema(db,-1), cnt++)==0) );
sqlcipher_sqlite3BtreeLeaveAll(db);
rc = sqlcipher_sqlite3ApiExit(db, rc);
@@ -134691,7 +140965,7 @@ SQLITE_API int sqlcipher_sqlite3_prepare16_v3(
*/
typedef struct DistinctCtx DistinctCtx;
struct DistinctCtx {
- u8 isTnct; /* True if the DISTINCT keyword is present */
+ u8 isTnct; /* 0: Not distinct. 1: DISTICT 2: DISTINCT and ORDER BY */
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 */
@@ -134755,12 +141029,16 @@ static void clearSelect(sqlcipher_sqlite3 *db, Select *p, int bFree){
sqlcipher_sqlite3ExprDelete(db, p->pHaving);
sqlcipher_sqlite3ExprListDelete(db, p->pOrderBy);
sqlcipher_sqlite3ExprDelete(db, p->pLimit);
+ if( OK_IF_ALWAYS_TRUE(p->pWith) ) sqlcipher_sqlite3WithDelete(db, p->pWith);
#ifndef SQLITE_OMIT_WINDOWFUNC
if( OK_IF_ALWAYS_TRUE(p->pWinDefn) ){
sqlcipher_sqlite3WindowListDelete(db, p->pWinDefn);
}
+ while( p->pWin ){
+ assert( p->pWin->ppThis==&p->pWin );
+ sqlcipher_sqlite3WindowUnlinkFromSelect(p->pWin);
+ }
#endif
- if( OK_IF_ALWAYS_TRUE(p->pWith) ) sqlcipher_sqlite3WithDelete(db, p->pWith);
if( bFree ) sqlcipher_sqlite3DbFreeNN(db, p);
p = pPrior;
bFree = 1;
@@ -134870,6 +141148,52 @@ static Select *findRightmost(Select *p){
**
** If an illegal or unsupported join type is seen, then still return
** a join type, but put an error in the pParse structure.
+**
+** These are the valid join types:
+**
+**
+** pA pB pC Return Value
+** ------- ----- ----- ------------
+** CROSS - - JT_CROSS
+** INNER - - JT_INNER
+** LEFT - - JT_LEFT|JT_OUTER
+** LEFT OUTER - JT_LEFT|JT_OUTER
+** RIGHT - - JT_RIGHT|JT_OUTER
+** RIGHT OUTER - JT_RIGHT|JT_OUTER
+** FULL - - JT_LEFT|JT_RIGHT|JT_OUTER
+** FULL OUTER - JT_LEFT|JT_RIGHT|JT_OUTER
+** NATURAL INNER - JT_NATURAL|JT_INNER
+** NATURAL LEFT - JT_NATURAL|JT_LEFT|JT_OUTER
+** NATURAL LEFT OUTER JT_NATURAL|JT_LEFT|JT_OUTER
+** NATURAL RIGHT - JT_NATURAL|JT_RIGHT|JT_OUTER
+** NATURAL RIGHT OUTER JT_NATURAL|JT_RIGHT|JT_OUTER
+** NATURAL FULL - JT_NATURAL|JT_LEFT|JT_RIGHT
+** NATURAL FULL OUTER JT_NATRUAL|JT_LEFT|JT_RIGHT
+**
+** To preserve historical compatibly, SQLite also accepts a variety
+** of other non-standard and in many cases non-sensical join types.
+** This routine makes as much sense at it can from the nonsense join
+** type and returns a result. Examples of accepted nonsense join types
+** include but are not limited to:
+**
+** INNER CROSS JOIN -> same as JOIN
+** NATURAL CROSS JOIN -> same as NATURAL JOIN
+** OUTER LEFT JOIN -> same as LEFT JOIN
+** LEFT NATURAL JOIN -> same as NATURAL LEFT JOIN
+** LEFT RIGHT JOIN -> same as FULL JOIN
+** RIGHT OUTER FULL JOIN -> same as FULL JOIN
+** CROSS CROSS CROSS JOIN -> same as JOIN
+**
+** The only restrictions on the join type name are:
+**
+** * "INNER" cannot appear together with "OUTER", "LEFT", "RIGHT",
+** or "FULL".
+**
+** * "CROSS" cannot appear together with "OUTER", "LEFT", "RIGHT,
+** or "FULL".
+**
+** * If "OUTER" is present then there must also be one of
+** "LEFT", "RIGHT", or "FULL"
*/
SQLITE_PRIVATE int sqlcipher_sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){
int jointype = 0;
@@ -134882,13 +141206,13 @@ SQLITE_PRIVATE int sqlcipher_sqlite3JoinType(Parse *pParse, Token *pA, Token *pB
u8 nChar; /* Length of the keyword in characters */
u8 code; /* Join type mask */
} aKeyword[] = {
- /* natural */ { 0, 7, JT_NATURAL },
- /* left */ { 6, 4, JT_LEFT|JT_OUTER },
- /* outer */ { 10, 5, JT_OUTER },
- /* right */ { 14, 5, JT_RIGHT|JT_OUTER },
- /* full */ { 19, 4, JT_LEFT|JT_RIGHT|JT_OUTER },
- /* inner */ { 23, 5, JT_INNER },
- /* cross */ { 28, 5, JT_INNER|JT_CROSS },
+ /* (0) natural */ { 0, 7, JT_NATURAL },
+ /* (1) left */ { 6, 4, JT_LEFT|JT_OUTER },
+ /* (2) outer */ { 10, 5, JT_OUTER },
+ /* (3) right */ { 14, 5, JT_RIGHT|JT_OUTER },
+ /* (4) full */ { 19, 4, JT_LEFT|JT_RIGHT|JT_OUTER },
+ /* (5) inner */ { 23, 5, JT_INNER },
+ /* (6) cross */ { 28, 5, JT_INNER|JT_CROSS },
};
int i, j;
apAll[0] = pA;
@@ -134911,18 +141235,15 @@ SQLITE_PRIVATE int sqlcipher_sqlite3JoinType(Parse *pParse, Token *pA, Token *pB
}
if(
(jointype & (JT_INNER|JT_OUTER))==(JT_INNER|JT_OUTER) ||
- (jointype & JT_ERROR)!=0
+ (jointype & JT_ERROR)!=0 ||
+ (jointype & (JT_OUTER|JT_LEFT|JT_RIGHT))==JT_OUTER
){
- const char *zSp = " ";
- assert( pB!=0 );
- if( pC==0 ){ zSp++; }
- sqlcipher_sqlite3ErrorMsg(pParse, "unknown or unsupported join type: "
- "%T %T%s%T", pA, pB, zSp, pC);
- jointype = JT_INNER;
- }else if( (jointype & JT_OUTER)!=0
- && (jointype & (JT_LEFT|JT_RIGHT))!=JT_LEFT ){
- sqlcipher_sqlite3ErrorMsg(pParse,
- "RIGHT and FULL OUTER JOINs are not currently supported");
+ const char *zSp1 = " ";
+ const char *zSp2 = " ";
+ if( pB==0 ){ zSp1++; }
+ if( pC==0 ){ zSp2++; }
+ sqlcipher_sqlite3ErrorMsg(pParse, "unknown join type: "
+ "%T%s%T%s%T", pA, zSp1, pB, zSp2, pC);
jointype = JT_INNER;
}
return jointype;
@@ -134932,19 +141253,36 @@ SQLITE_PRIVATE int sqlcipher_sqlite3JoinType(Parse *pParse, Token *pA, Token *pB
** Return the index of a column in a table. Return -1 if the column
** is not contained in the table.
*/
-static int columnIndex(Table *pTab, const char *zCol){
+SQLITE_PRIVATE int sqlcipher_sqlite3ColumnIndex(Table *pTab, const char *zCol){
int i;
u8 h = sqlcipher_sqlite3StrIHash(zCol);
Column *pCol;
for(pCol=pTab->aCol, i=0; i<pTab->nCol; pCol++, i++){
- if( pCol->hName==h && sqlcipher_sqlite3StrICmp(pCol->zName, zCol)==0 ) return i;
+ if( pCol->hName==h && sqlcipher_sqlite3StrICmp(pCol->zCnName, zCol)==0 ) return i;
}
return -1;
}
/*
-** Search the first N tables in pSrc, from left to right, looking for a
-** table that has a column named zCol.
+** Mark a subquery result column as having been used.
+*/
+SQLITE_PRIVATE void sqlcipher_sqlite3SrcItemColumnUsed(SrcItem *pItem, int iCol){
+ assert( pItem!=0 );
+ assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem->pSelect) );
+ if( pItem->fg.isNestedFrom ){
+ ExprList *pResults;
+ assert( pItem->pSelect!=0 );
+ pResults = pItem->pSelect->pEList;
+ assert( pResults!=0 );
+ assert( iCol>=0 && iCol<pResults->nExpr );
+ pResults->a[iCol].fg.bUsed = 1;
+ }
+}
+
+/*
+** Search the tables iStart..iEnd (inclusive) in pSrc, looking for a
+** table that has a column named zCol. The search is left-to-right.
+** The first match found is returned.
**
** When found, set *piTab and *piCol to the table index and column index
** of the matching column and return TRUE.
@@ -134953,22 +141291,27 @@ static int columnIndex(Table *pTab, const char *zCol){
*/
static int tableAndColumnIndex(
SrcList *pSrc, /* Array of tables to search */
- int N, /* Number of tables in pSrc->a[] to search */
+ int iStart, /* First member of pSrc->a[] to check */
+ int iEnd, /* Last member of pSrc->a[] to check */
const char *zCol, /* Name of the column we are looking for */
int *piTab, /* Write index of pSrc->a[] here */
int *piCol, /* Write index of pSrc->a[*piTab].pTab->aCol[] here */
- int bIgnoreHidden /* True to ignore hidden columns */
+ int bIgnoreHidden /* Ignore hidden columns */
){
int i; /* For looping over tables in pSrc */
int iCol; /* Index of column matching zCol */
+ assert( iEnd<pSrc->nSrc );
+ assert( iStart>=0 );
assert( (piTab==0)==(piCol==0) ); /* Both or neither are NULL */
- for(i=0; i<N; i++){
- iCol = columnIndex(pSrc->a[i].pTab, zCol);
+
+ for(i=iStart; i<=iEnd; i++){
+ iCol = sqlcipher_sqlite3ColumnIndex(pSrc->a[i].pTab, zCol);
if( iCol>=0
&& (bIgnoreHidden==0 || IsHiddenColumn(&pSrc->a[i].pTab->aCol[iCol])==0)
){
if( piTab ){
+ sqlcipher_sqlite3SrcItemColumnUsed(&pSrc->a[i], iCol);
*piTab = i;
*piCol = iCol;
}
@@ -134979,63 +141322,19 @@ static int tableAndColumnIndex(
}
/*
-** This function is used to add terms implied by JOIN syntax to the
-** WHERE clause expression of a SELECT statement. The new term, which
-** is ANDed with the existing WHERE clause, is of the form:
-**
-** (tab1.col1 = tab2.col2)
-**
-** where tab1 is the iSrc'th table in SrcList pSrc and tab2 is the
-** (iSrc+1)'th. Column col1 is column iColLeft of tab1, and col2 is
-** column iColRight of tab2.
-*/
-static void addWhereTerm(
- Parse *pParse, /* Parsing context */
- SrcList *pSrc, /* List of tables in FROM clause */
- int iLeft, /* Index of first table to join in pSrc */
- int iColLeft, /* Index of column in first table */
- int iRight, /* Index of second table in pSrc */
- int iColRight, /* Index of column in second table */
- int isOuterJoin, /* True if this is an OUTER join */
- Expr **ppWhere /* IN/OUT: The WHERE clause to add to */
-){
- sqlcipher_sqlite3 *db = pParse->db;
- Expr *pE1;
- Expr *pE2;
- Expr *pEq;
-
- assert( iLeft<iRight );
- assert( pSrc->nSrc>iRight );
- assert( pSrc->a[iLeft].pTab );
- assert( pSrc->a[iRight].pTab );
-
- pE1 = sqlcipher_sqlite3CreateColumnExpr(db, pSrc, iLeft, iColLeft);
- pE2 = sqlcipher_sqlite3CreateColumnExpr(db, pSrc, iRight, iColRight);
-
- pEq = sqlcipher_sqlite3PExpr(pParse, TK_EQ, pE1, pE2);
- if( pEq && isOuterJoin ){
- ExprSetProperty(pEq, EP_FromJoin);
- assert( !ExprHasProperty(pEq, EP_TokenOnly|EP_Reduced) );
- ExprSetVVAProperty(pEq, EP_NoReduce);
- pEq->iRightJoinTable = (i16)pE2->iTable;
- }
- *ppWhere = sqlcipher_sqlite3ExprAnd(pParse, *ppWhere, pEq);
-}
-
-/*
-** Set the EP_FromJoin property on all terms of the given expression.
-** And set the Expr.iRightJoinTable to iTable for every term in the
+** Set the EP_OuterON property on all terms of the given expression.
+** And set the Expr.w.iJoin to iTable for every term in the
** expression.
**
-** The EP_FromJoin property is used on terms of an expression to tell
-** the LEFT OUTER JOIN processing logic that this term is part of the
+** The EP_OuterON property is used on terms of an expression to tell
+** the OUTER JOIN processing logic that this term is part of the
** join restriction specified in the ON or USING clause and not a part
** of the more general WHERE clause. These terms are moved over to the
** WHERE clause during join processing but we need to remember that they
** originated in the ON or USING clause.
**
-** The Expr.iRightJoinTable tells the WHERE clause processing that the
-** expression depends on table iRightJoinTable even if that table is not
+** The Expr.w.iJoin tells the WHERE clause processing that the
+** expression depends on table w.iJoin even if that table is not
** explicitly mentioned in the expression. That information is needed
** for cases like this:
**
@@ -135048,114 +141347,131 @@ static void addWhereTerm(
** after the t1 loop and rows with t1.x!=5 will never appear in
** the output, which is incorrect.
*/
-SQLITE_PRIVATE void sqlcipher_sqlite3SetJoinExpr(Expr *p, int iTable){
+SQLITE_PRIVATE void sqlcipher_sqlite3SetJoinExpr(Expr *p, int iTable, u32 joinFlag){
+ assert( joinFlag==EP_OuterON || joinFlag==EP_InnerON );
while( p ){
- ExprSetProperty(p, EP_FromJoin);
+ ExprSetProperty(p, joinFlag);
assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
ExprSetVVAProperty(p, EP_NoReduce);
- p->iRightJoinTable = (i16)iTable;
- if( p->op==TK_FUNCTION && p->x.pList ){
- int i;
- for(i=0; i<p->x.pList->nExpr; i++){
- sqlcipher_sqlite3SetJoinExpr(p->x.pList->a[i].pExpr, iTable);
+ p->w.iJoin = iTable;
+ if( p->op==TK_FUNCTION ){
+ assert( ExprUseXList(p) );
+ if( p->x.pList ){
+ int i;
+ for(i=0; i<p->x.pList->nExpr; i++){
+ sqlcipher_sqlite3SetJoinExpr(p->x.pList->a[i].pExpr, iTable, joinFlag);
+ }
}
}
- sqlcipher_sqlite3SetJoinExpr(p->pLeft, iTable);
+ sqlcipher_sqlite3SetJoinExpr(p->pLeft, iTable, joinFlag);
p = p->pRight;
}
}
-/* Undo the work of sqlcipher_sqlite3SetJoinExpr(). In the expression p, convert every
-** term that is marked with EP_FromJoin and iRightJoinTable==iTable into
-** an ordinary term that omits the EP_FromJoin mark.
+/* Undo the work of sqlcipher_sqlite3SetJoinExpr(). This is used when a LEFT JOIN
+** is simplified into an ordinary JOIN, and when an ON expression is
+** "pushed down" into the WHERE clause of a subquery.
**
-** This happens when a LEFT JOIN is simplified into an ordinary JOIN.
+** Convert every term that is marked with EP_OuterON and w.iJoin==iTable into
+** an ordinary term that omits the EP_OuterON mark. Or if iTable<0, then
+** just clear every EP_OuterON and EP_InnerON mark from the expression tree.
+**
+** If nullable is true, that means that Expr p might evaluate to NULL even
+** if it is a reference to a NOT NULL column. This can happen, for example,
+** if the table that p references is on the left side of a RIGHT JOIN.
+** If nullable is true, then take care to not remove the EP_CanBeNull bit.
+** See forum thread https://sqlite.org/forum/forumpost/b40696f50145d21c
*/
-static void unsetJoinExpr(Expr *p, int iTable){
+static void unsetJoinExpr(Expr *p, int iTable, int nullable){
while( p ){
- if( ExprHasProperty(p, EP_FromJoin)
- && (iTable<0 || p->iRightJoinTable==iTable) ){
- ExprClearProperty(p, EP_FromJoin);
+ if( iTable<0 || (ExprHasProperty(p, EP_OuterON) && p->w.iJoin==iTable) ){
+ ExprClearProperty(p, EP_OuterON|EP_InnerON);
+ if( iTable>=0 ) ExprSetProperty(p, EP_InnerON);
}
- if( p->op==TK_FUNCTION && p->x.pList ){
- int i;
- for(i=0; i<p->x.pList->nExpr; i++){
- unsetJoinExpr(p->x.pList->a[i].pExpr, iTable);
+ if( p->op==TK_COLUMN && p->iTable==iTable && !nullable ){
+ ExprClearProperty(p, EP_CanBeNull);
+ }
+ if( p->op==TK_FUNCTION ){
+ assert( ExprUseXList(p) );
+ if( p->x.pList ){
+ int i;
+ for(i=0; i<p->x.pList->nExpr; i++){
+ unsetJoinExpr(p->x.pList->a[i].pExpr, iTable, nullable);
+ }
}
}
- unsetJoinExpr(p->pLeft, iTable);
+ unsetJoinExpr(p->pLeft, iTable, nullable);
p = p->pRight;
}
}
/*
** This routine processes the join information for a SELECT statement.
-** ON and USING clauses are converted into extra terms of the WHERE clause.
-** NATURAL joins also create extra WHERE clause terms.
+**
+** * A NATURAL join is converted into a USING join. After that, we
+** do not need to be concerned with NATURAL joins and we only have
+** think about USING joins.
+**
+** * ON and USING clauses result in extra terms being added to the
+** WHERE clause to enforce the specified constraints. The extra
+** WHERE clause terms will be tagged with EP_OuterON or
+** EP_InnerON so that we know that they originated in ON/USING.
**
** The terms of a FROM clause are contained in the Select.pSrc structure.
** The left most table is the first entry in Select.pSrc. The right-most
** table is the last entry. The join operator is held in the entry to
-** the left. Thus entry 0 contains the join operator for the join between
+** the right. Thus entry 1 contains the join operator for the join between
** entries 0 and 1. Any ON or USING clauses associated with the join are
-** also attached to the left entry.
+** also attached to the right entry.
**
** This routine returns the number of errors encountered.
*/
-static int sqliteProcessJoin(Parse *pParse, Select *p){
+static int sqlcipher_sqlite3ProcessJoin(Parse *pParse, Select *p){
SrcList *pSrc; /* All tables in the FROM clause */
int i, j; /* Loop counters */
- struct SrcList_item *pLeft; /* Left table being joined */
- struct SrcList_item *pRight; /* Right table being joined */
+ SrcItem *pLeft; /* Left table being joined */
+ SrcItem *pRight; /* Right table being joined */
pSrc = p->pSrc;
pLeft = &pSrc->a[0];
pRight = &pLeft[1];
for(i=0; i<pSrc->nSrc-1; i++, pRight++, pLeft++){
Table *pRightTab = pRight->pTab;
- int isOuter;
+ u32 joinType;
if( NEVER(pLeft->pTab==0 || pRightTab==0) ) continue;
- isOuter = (pRight->fg.jointype & JT_OUTER)!=0;
+ joinType = (pRight->fg.jointype & JT_OUTER)!=0 ? EP_OuterON : EP_InnerON;
- /* When the NATURAL keyword is present, add WHERE clause terms for
- ** every column that the two tables have in common.
+ /* If this is a NATURAL join, synthesize an approprate USING clause
+ ** to specify which columns should be joined.
*/
if( pRight->fg.jointype & JT_NATURAL ){
- if( pRight->pOn || pRight->pUsing ){
+ IdList *pUsing = 0;
+ if( pRight->fg.isUsing || pRight->u3.pOn ){
sqlcipher_sqlite3ErrorMsg(pParse, "a NATURAL join may not have "
"an ON or USING clause", 0);
return 1;
}
for(j=0; j<pRightTab->nCol; j++){
char *zName; /* Name of column in the right table */
- int iLeft; /* Matching left table */
- int iLeftCol; /* Matching column in the left table */
if( IsHiddenColumn(&pRightTab->aCol[j]) ) continue;
- zName = pRightTab->aCol[j].zName;
- if( tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol, 1) ){
- addWhereTerm(pParse, pSrc, iLeft, iLeftCol, i+1, j,
- isOuter, &p->pWhere);
+ zName = pRightTab->aCol[j].zCnName;
+ if( tableAndColumnIndex(pSrc, 0, i, zName, 0, 0, 1) ){
+ pUsing = sqlcipher_sqlite3IdListAppend(pParse, pUsing, 0);
+ if( pUsing ){
+ assert( pUsing->nId>0 );
+ assert( pUsing->a[pUsing->nId-1].zName==0 );
+ pUsing->a[pUsing->nId-1].zName = sqlcipher_sqlite3DbStrDup(pParse->db, zName);
+ }
}
}
- }
-
- /* Disallow both ON and USING clauses in the same join
- */
- if( pRight->pOn && pRight->pUsing ){
- sqlcipher_sqlite3ErrorMsg(pParse, "cannot have both ON and USING "
- "clauses in the same join");
- return 1;
- }
-
- /* Add the ON clause to the end of the WHERE clause, connected by
- ** an AND operator.
- */
- if( pRight->pOn ){
- if( isOuter ) sqlcipher_sqlite3SetJoinExpr(pRight->pOn, pRight->iCursor);
- p->pWhere = sqlcipher_sqlite3ExprAnd(pParse, p->pWhere, pRight->pOn);
- pRight->pOn = 0;
+ if( pUsing ){
+ pRight->fg.isUsing = 1;
+ pRight->fg.isSynthUsing = 1;
+ pRight->u3.pUsing = pUsing;
+ }
+ if( pParse->nErr ) return 1;
}
/* Create extra terms on the WHERE clause for each column named
@@ -135165,27 +141481,88 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
** Report an error if any column mentioned in the USING clause is
** not contained in both tables to be joined.
*/
- if( pRight->pUsing ){
- IdList *pList = pRight->pUsing;
+ if( pRight->fg.isUsing ){
+ IdList *pList = pRight->u3.pUsing;
+ sqlcipher_sqlite3 *db = pParse->db;
+ assert( pList!=0 );
for(j=0; j<pList->nId; j++){
char *zName; /* Name of the term in the USING clause */
int iLeft; /* Table on the left with matching column name */
int iLeftCol; /* Column number of matching column on the left */
int iRightCol; /* Column number of matching column on the right */
+ Expr *pE1; /* Reference to the column on the LEFT of the join */
+ Expr *pE2; /* Reference to the column on the RIGHT of the join */
+ Expr *pEq; /* Equality constraint. pE1 == pE2 */
zName = pList->a[j].zName;
- iRightCol = columnIndex(pRightTab, zName);
+ iRightCol = sqlcipher_sqlite3ColumnIndex(pRightTab, zName);
if( iRightCol<0
- || !tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol, 0)
+ || tableAndColumnIndex(pSrc, 0, i, zName, &iLeft, &iLeftCol,
+ pRight->fg.isSynthUsing)==0
){
sqlcipher_sqlite3ErrorMsg(pParse, "cannot join using column %s - column "
"not present in both tables", zName);
return 1;
}
- addWhereTerm(pParse, pSrc, iLeft, iLeftCol, i+1, iRightCol,
- isOuter, &p->pWhere);
+ pE1 = sqlcipher_sqlite3CreateColumnExpr(db, pSrc, iLeft, iLeftCol);
+ sqlcipher_sqlite3SrcItemColumnUsed(&pSrc->a[iLeft], iLeftCol);
+ if( (pSrc->a[0].fg.jointype & JT_LTORJ)!=0 ){
+ /* This branch runs if the query contains one or more RIGHT or FULL
+ ** JOINs. If only a single table on the left side of this join
+ ** contains the zName column, then this branch is a no-op.
+ ** But if there are two or more tables on the left side
+ ** of the join, construct a coalesce() function that gathers all
+ ** such tables. Raise an error if more than one of those references
+ ** to zName is not also within a prior USING clause.
+ **
+ ** We really ought to raise an error if there are two or more
+ ** non-USING references to zName on the left of an INNER or LEFT
+ ** JOIN. But older versions of SQLite do not do that, so we avoid
+ ** adding a new error so as to not break legacy applications.
+ */
+ ExprList *pFuncArgs = 0; /* Arguments to the coalesce() */
+ static const Token tkCoalesce = { "coalesce", 8 };
+ while( tableAndColumnIndex(pSrc, iLeft+1, i, zName, &iLeft, &iLeftCol,
+ pRight->fg.isSynthUsing)!=0 ){
+ if( pSrc->a[iLeft].fg.isUsing==0
+ || sqlcipher_sqlite3IdListIndex(pSrc->a[iLeft].u3.pUsing, zName)<0
+ ){
+ sqlcipher_sqlite3ErrorMsg(pParse, "ambiguous reference to %s in USING()",
+ zName);
+ break;
+ }
+ pFuncArgs = sqlcipher_sqlite3ExprListAppend(pParse, pFuncArgs, pE1);
+ pE1 = sqlcipher_sqlite3CreateColumnExpr(db, pSrc, iLeft, iLeftCol);
+ sqlcipher_sqlite3SrcItemColumnUsed(&pSrc->a[iLeft], iLeftCol);
+ }
+ if( pFuncArgs ){
+ pFuncArgs = sqlcipher_sqlite3ExprListAppend(pParse, pFuncArgs, pE1);
+ pE1 = sqlcipher_sqlite3ExprFunction(pParse, pFuncArgs, &tkCoalesce, 0);
+ }
+ }
+ pE2 = sqlcipher_sqlite3CreateColumnExpr(db, pSrc, i+1, iRightCol);
+ sqlcipher_sqlite3SrcItemColumnUsed(pRight, iRightCol);
+ pEq = sqlcipher_sqlite3PExpr(pParse, TK_EQ, pE1, pE2);
+ assert( pE2!=0 || pEq==0 );
+ if( pEq ){
+ ExprSetProperty(pEq, joinType);
+ assert( !ExprHasProperty(pEq, EP_TokenOnly|EP_Reduced) );
+ ExprSetVVAProperty(pEq, EP_NoReduce);
+ pEq->w.iJoin = pE2->iTable;
+ }
+ p->pWhere = sqlcipher_sqlite3ExprAnd(pParse, p->pWhere, pEq);
}
}
+
+ /* Add the ON clause to the end of the WHERE clause, connected by
+ ** an AND operator.
+ */
+ else if( pRight->u3.pOn ){
+ sqlcipher_sqlite3SetJoinExpr(pRight->u3.pOn, pRight->iCursor, joinType);
+ p->pWhere = sqlcipher_sqlite3ExprAnd(pParse, p->pWhere, pRight->u3.pOn);
+ pRight->u3.pOn = 0;
+ pRight->fg.isOn = 1;
+ }
}
return 0;
}
@@ -135404,31 +141781,157 @@ static void codeOffset(
}
/*
-** Add code that will check to make sure the N registers starting at iMem
-** form a distinct entry. iTab is a sorting index that holds previously
-** seen combinations of the N values. A new entry is made in iTab
-** if the current N values are new.
+** Add code that will check to make sure the array of registers starting at
+** iMem form a distinct entry. This is used by both "SELECT DISTINCT ..." and
+** distinct aggregates ("SELECT count(DISTINCT <expr>) ..."). Three strategies
+** are available. Which is used depends on the value of parameter eTnctType,
+** as follows:
**
-** A jump to addrRepeat is made and the N+1 values are popped from the
-** stack if the top N elements are not distinct.
-*/
-static void codeDistinct(
+** WHERE_DISTINCT_UNORDERED/WHERE_DISTINCT_NOOP:
+** Build an ephemeral table that contains all entries seen before and
+** skip entries which have been seen before.
+**
+** Parameter iTab is the cursor number of an ephemeral table that must
+** be opened before the VM code generated by this routine is executed.
+** The ephemeral cursor table is queried for a record identical to the
+** record formed by the current array of registers. If one is found,
+** jump to VM address addrRepeat. Otherwise, insert a new record into
+** the ephemeral cursor and proceed.
+**
+** The returned value in this case is a copy of parameter iTab.
+**
+** WHERE_DISTINCT_ORDERED:
+** In this case rows are being delivered sorted order. The ephermal
+** table is not required. Instead, the current set of values
+** is compared against previous row. If they match, the new row
+** is not distinct and control jumps to VM address addrRepeat. Otherwise,
+** the VM program proceeds with processing the new row.
+**
+** The returned value in this case is the register number of the first
+** in an array of registers used to store the previous result row so that
+** it can be compared to the next. The caller must ensure that this
+** register is initialized to NULL. (The fixDistinctOpenEph() routine
+** will take care of this initialization.)
+**
+** WHERE_DISTINCT_UNIQUE:
+** In this case it has already been determined that the rows are distinct.
+** No special action is required. The return value is zero.
+**
+** Parameter pEList is the list of expressions used to generated the
+** contents of each row. It is used by this routine to determine (a)
+** how many elements there are in the array of registers and (b) the
+** collation sequences that should be used for the comparisons if
+** eTnctType is WHERE_DISTINCT_ORDERED.
+*/
+static int codeDistinct(
Parse *pParse, /* Parsing and code generating context */
+ int eTnctType, /* WHERE_DISTINCT_* value */
int iTab, /* A sorting index used to test for distinctness */
int addrRepeat, /* Jump to here if not distinct */
- int N, /* Number of elements */
- int iMem /* First element */
+ ExprList *pEList, /* Expression for each element */
+ int regElem /* First element */
){
- Vdbe *v;
- int r1;
+ int iRet = 0;
+ int nResultCol = pEList->nExpr;
+ Vdbe *v = pParse->pVdbe;
- v = pParse->pVdbe;
- r1 = sqlcipher_sqlite3GetTempReg(pParse);
- sqlcipher_sqlite3VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, iMem, N); VdbeCoverage(v);
- sqlcipher_sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, N, r1);
- sqlcipher_sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iTab, r1, iMem, N);
- sqlcipher_sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
- sqlcipher_sqlite3ReleaseTempReg(pParse, r1);
+ switch( eTnctType ){
+ case WHERE_DISTINCT_ORDERED: {
+ int i;
+ int iJump; /* Jump destination */
+ int regPrev; /* Previous row content */
+
+ /* Allocate space for the previous row */
+ iRet = regPrev = pParse->nMem+1;
+ pParse->nMem += nResultCol;
+
+ iJump = sqlcipher_sqlite3VdbeCurrentAddr(v) + nResultCol;
+ for(i=0; i<nResultCol; i++){
+ CollSeq *pColl = sqlcipher_sqlite3ExprCollSeq(pParse, pEList->a[i].pExpr);
+ if( i<nResultCol-1 ){
+ sqlcipher_sqlite3VdbeAddOp3(v, OP_Ne, regElem+i, iJump, regPrev+i);
+ VdbeCoverage(v);
+ }else{
+ sqlcipher_sqlite3VdbeAddOp3(v, OP_Eq, regElem+i, addrRepeat, regPrev+i);
+ VdbeCoverage(v);
+ }
+ sqlcipher_sqlite3VdbeChangeP4(v, -1, (const char *)pColl, P4_COLLSEQ);
+ sqlcipher_sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
+ }
+ assert( sqlcipher_sqlite3VdbeCurrentAddr(v)==iJump || pParse->db->mallocFailed );
+ sqlcipher_sqlite3VdbeAddOp3(v, OP_Copy, regElem, regPrev, nResultCol-1);
+ break;
+ }
+
+ case WHERE_DISTINCT_UNIQUE: {
+ /* nothing to do */
+ break;
+ }
+
+ default: {
+ int r1 = sqlcipher_sqlite3GetTempReg(pParse);
+ sqlcipher_sqlite3VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, regElem, nResultCol);
+ VdbeCoverage(v);
+ sqlcipher_sqlite3VdbeAddOp3(v, OP_MakeRecord, regElem, nResultCol, r1);
+ sqlcipher_sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iTab, r1, regElem, nResultCol);
+ sqlcipher_sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
+ sqlcipher_sqlite3ReleaseTempReg(pParse, r1);
+ iRet = iTab;
+ break;
+ }
+ }
+
+ return iRet;
+}
+
+/*
+** This routine runs after codeDistinct(). It makes necessary
+** adjustments to the OP_OpenEphemeral opcode that the codeDistinct()
+** routine made use of. This processing must be done separately since
+** sometimes codeDistinct is called before the OP_OpenEphemeral is actually
+** laid down.
+**
+** WHERE_DISTINCT_NOOP:
+** WHERE_DISTINCT_UNORDERED:
+**
+** No adjustments necessary. This function is a no-op.
+**
+** WHERE_DISTINCT_UNIQUE:
+**
+** The ephemeral table is not needed. So change the
+** OP_OpenEphemeral opcode into an OP_Noop.
+**
+** WHERE_DISTINCT_ORDERED:
+**
+** The ephemeral table is not needed. But we do need register
+** iVal to be initialized to NULL. So change the OP_OpenEphemeral
+** into an OP_Null on the iVal register.
+*/
+static void fixDistinctOpenEph(
+ Parse *pParse, /* Parsing and code generating context */
+ int eTnctType, /* WHERE_DISTINCT_* value */
+ int iVal, /* Value returned by codeDistinct() */
+ int iOpenEphAddr /* Address of OP_OpenEphemeral instruction for iTab */
+){
+ if( pParse->nErr==0
+ && (eTnctType==WHERE_DISTINCT_UNIQUE || eTnctType==WHERE_DISTINCT_ORDERED)
+ ){
+ Vdbe *v = pParse->pVdbe;
+ sqlcipher_sqlite3VdbeChangeToNoop(v, iOpenEphAddr);
+ if( sqlcipher_sqlite3VdbeGetOp(v, iOpenEphAddr+1)->opcode==OP_Explain ){
+ sqlcipher_sqlite3VdbeChangeToNoop(v, iOpenEphAddr+1);
+ }
+ if( eTnctType==WHERE_DISTINCT_ORDERED ){
+ /* Change the OP_OpenEphemeral to an OP_Null that sets the MEM_Cleared
+ ** bit on the first register of the previous value. This will cause the
+ ** OP_Ne added in codeDistinct() to always fail on the first iteration of
+ ** the loop even if the first row is all NULLs. */
+ VdbeOp *pOp = sqlcipher_sqlite3VdbeGetOp(v, iOpenEphAddr);
+ pOp->opcode = OP_Null;
+ pOp->p1 = 1;
+ pOp->p2 = iVal;
+ }
+ }
}
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
@@ -135448,7 +141951,7 @@ static void codeDistinct(
** retrieved directly from table t1. If the values are very large, this
** can be more efficient than storing them directly in the sorter records.
**
-** The ExprList_item.bSorterRef flag is set for each expression in pEList
+** The ExprList_item.fg.bSorterRef flag is set for each expression in pEList
** for which the sorter-reference optimization should be enabled.
** Additionally, the pSort->aDefer[] array is populated with entries
** for all cursors required to evaluate all selected expressions. Finally.
@@ -135469,9 +141972,13 @@ static void selectExprDefer(
struct ExprList_item *pItem = &pEList->a[i];
if( pItem->u.x.iOrderByCol==0 ){
Expr *pExpr = pItem->pExpr;
- Table *pTab = pExpr->y.pTab;
- if( pExpr->op==TK_COLUMN && pExpr->iColumn>=0 && pTab && !IsVirtual(pTab)
- && (pTab->aCol[pExpr->iColumn].colFlags & COLFLAG_SORTERREF)
+ Table *pTab;
+ if( pExpr->op==TK_COLUMN
+ && pExpr->iColumn>=0
+ && ALWAYS( ExprUseYTab(pExpr) )
+ && (pTab = pExpr->y.pTab)!=0
+ && IsOrdinaryTable(pTab)
+ && (pTab->aCol[pExpr->iColumn].colFlags & COLFLAG_SORTERREF)!=0
){
int j;
for(j=0; j<nDefer; j++){
@@ -135492,6 +141999,7 @@ static void selectExprDefer(
Expr *pNew = sqlcipher_sqlite3PExpr(pParse, TK_COLUMN, 0, 0);
if( pNew ){
pNew->iTable = pExpr->iTable;
+ assert( ExprUseYTab(pNew) );
pNew->y.pTab = pExpr->y.pTab;
pNew->iColumn = pPk ? pPk->aiColumn[k] : -1;
pExtra = sqlcipher_sqlite3ExprListAppend(pParse, pExtra, pNew);
@@ -135503,7 +142011,7 @@ static void selectExprDefer(
nDefer++;
}
}
- pItem->bSorterRef = 1;
+ pItem->fg.bSorterRef = 1;
}
}
}
@@ -135634,7 +142142,7 @@ static void selectInnerLoop(
for(i=0; i<pEList->nExpr; i++){
if( pEList->a[i].u.x.iOrderByCol>0
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
- || pEList->a[i].bSorterRef
+ || pEList->a[i].fg.bSorterRef
#endif
){
nResultCol--;
@@ -135676,59 +142184,11 @@ static void selectInnerLoop(
** part of the result.
*/
if( hasDistinct ){
- switch( pDistinct->eTnctType ){
- case WHERE_DISTINCT_ORDERED: {
- VdbeOp *pOp; /* No longer required OpenEphemeral instr. */
- int iJump; /* Jump destination */
- int regPrev; /* Previous row content */
-
- /* Allocate space for the previous row */
- regPrev = pParse->nMem+1;
- pParse->nMem += nResultCol;
-
- /* Change the OP_OpenEphemeral coded earlier to an OP_Null
- ** sets the MEM_Cleared bit on the first register of the
- ** previous value. This will cause the OP_Ne below to always
- ** fail on the first iteration of the loop even if the first
- ** row is all NULLs.
- */
- sqlcipher_sqlite3VdbeChangeToNoop(v, pDistinct->addrTnct);
- pOp = sqlcipher_sqlite3VdbeGetOp(v, pDistinct->addrTnct);
- pOp->opcode = OP_Null;
- pOp->p1 = 1;
- pOp->p2 = regPrev;
- pOp = 0; /* Ensure pOp is not used after sqlcipher_sqlite3VdbeAddOp() */
-
- iJump = sqlcipher_sqlite3VdbeCurrentAddr(v) + nResultCol;
- for(i=0; i<nResultCol; i++){
- CollSeq *pColl = sqlcipher_sqlite3ExprCollSeq(pParse, p->pEList->a[i].pExpr);
- if( i<nResultCol-1 ){
- sqlcipher_sqlite3VdbeAddOp3(v, OP_Ne, regResult+i, iJump, regPrev+i);
- VdbeCoverage(v);
- }else{
- sqlcipher_sqlite3VdbeAddOp3(v, OP_Eq, regResult+i, iContinue, regPrev+i);
- VdbeCoverage(v);
- }
- sqlcipher_sqlite3VdbeChangeP4(v, -1, (const char *)pColl, P4_COLLSEQ);
- sqlcipher_sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
- }
- assert( sqlcipher_sqlite3VdbeCurrentAddr(v)==iJump || pParse->db->mallocFailed );
- sqlcipher_sqlite3VdbeAddOp3(v, OP_Copy, regResult, regPrev, nResultCol-1);
- break;
- }
-
- case WHERE_DISTINCT_UNIQUE: {
- sqlcipher_sqlite3VdbeChangeToNoop(v, pDistinct->addrTnct);
- break;
- }
-
- default: {
- assert( pDistinct->eTnctType==WHERE_DISTINCT_UNORDERED );
- codeDistinct(pParse, pDistinct->tabTnct, iContinue, nResultCol,
- regResult);
- break;
- }
- }
+ int eType = pDistinct->eTnctType;
+ int iTab = pDistinct->tabTnct;
+ assert( nResultCol==p->pEList->nExpr );
+ iTab = codeDistinct(pParse, eType, iTab, iContinue, p->pEList, regResult);
+ fixDistinctOpenEph(pParse, eType, iTab, pDistinct->addrTnct);
if( pSort==0 ){
codeOffset(v, p->iOffset, iContinue);
}
@@ -135975,7 +142435,7 @@ SQLITE_PRIVATE KeyInfo *sqlcipher_sqlite3KeyInfoAlloc(sqlcipher_sqlite3 *db, int
p->nRef = 1;
memset(&p[1], 0, nExtra);
}else{
- sqlcipher_sqlite3OomFault(db);
+ return (KeyInfo*)sqlcipher_sqlite3OomFault(db);
}
return p;
}
@@ -136044,7 +142504,7 @@ SQLITE_PRIVATE KeyInfo *sqlcipher_sqlite3KeyInfoFromExprList(
assert( sqlcipher_sqlite3KeyInfoIsWriteable(pInfo) );
for(i=iStart, pItem=pList->a+iStart; i<nExpr; i++, pItem++){
pInfo->aColl[i-iStart] = sqlcipher_sqlite3ExprNNCollSeq(pParse, pItem->pExpr);
- pInfo->aSortFlags[i-iStart] = pItem->sortFlags;
+ pInfo->aSortFlags[i-iStart] = pItem->fg.sortFlags;
}
}
return pInfo;
@@ -136053,7 +142513,7 @@ SQLITE_PRIVATE KeyInfo *sqlcipher_sqlite3KeyInfoFromExprList(
/*
** Name of the connection operator, used for error messages.
*/
-static const char *selectOpName(int id){
+SQLITE_PRIVATE const char *sqlcipher_sqlite3SelectOpName(int id){
char *z;
switch( id ){
case TK_ALL: z = "UNION ALL"; break;
@@ -136146,6 +142606,9 @@ static void generateSortTail(
iTab = pSort->iECursor;
if( eDest==SRT_Output || eDest==SRT_Coroutine || eDest==SRT_Mem ){
+ if( eDest==SRT_Mem && p->iOffset ){
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_Null, 0, pDest->iSdst);
+ }
regRowid = 0;
regRow = pDest->iSdst;
}else{
@@ -136169,7 +142632,7 @@ static void generateSortTail(
if( addrOnce ) sqlcipher_sqlite3VdbeJumpHere(v, addrOnce);
addr = 1 + sqlcipher_sqlite3VdbeAddOp2(v, OP_SorterSort, iTab, addrBreak);
VdbeCoverage(v);
- codeOffset(v, p->iOffset, addrContinue);
+ assert( p->iLimit==0 && p->iOffset==0 );
sqlcipher_sqlite3VdbeAddOp3(v, OP_SorterData, iTab, regSortOut, iSortTab);
bSeq = 0;
}else{
@@ -136177,10 +142640,13 @@ static void generateSortTail(
codeOffset(v, p->iOffset, addrContinue);
iSortTab = iTab;
bSeq = 1;
+ if( p->iOffset>0 ){
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_AddImm, p->iLimit, -1);
+ }
}
for(i=0, iCol=nKey+bSeq-1; i<nColumn; i++){
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
- if( aOutEx[i].bSorterRef ) continue;
+ if( aOutEx[i].fg.bSorterRef ) continue;
#endif
if( aOutEx[i].u.x.iOrderByCol==0 ) iCol++;
}
@@ -136217,7 +142683,7 @@ static void generateSortTail(
#endif
for(i=nColumn-1; i>=0; i--){
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
- if( aOutEx[i].bSorterRef ){
+ if( aOutEx[i].fg.bSorterRef ){
sqlcipher_sqlite3ExprCode(pParse, aOutEx[i].pExpr, regRow+i);
}else
#endif
@@ -136388,13 +142854,19 @@ static const char *columnTypeImpl(
break;
}
- assert( pTab && pExpr->y.pTab==pTab );
+ assert( pTab && ExprUseYTab(pExpr) && pExpr->y.pTab==pTab );
if( pS ){
/* The "table" is actually a sub-select or a view in the FROM clause
** of the SELECT statement. Return the declaration type and origin
** data for the result-set column of the sub-select.
*/
- if( iCol>=0 && iCol<pS->pEList->nExpr ){
+ if( iCol<pS->pEList->nExpr
+#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
+ && iCol>=0
+#else
+ && ALWAYS(iCol>=0)
+#endif
+ ){
/* If iCol is less than zero, then the expression requests the
** rowid of the sub-select or view. This expression is legal (see
** test case misc2.2.2) - it always evaluates to NULL.
@@ -136416,7 +142888,7 @@ static const char *columnTypeImpl(
zType = "INTEGER";
zOrigCol = "rowid";
}else{
- zOrigCol = pTab->aCol[iCol].zName;
+ zOrigCol = pTab->aCol[iCol].zCnName;
zType = sqlcipher_sqlite3ColumnType(&pTab->aCol[iCol],0);
}
zOrigTab = pTab->zName;
@@ -136442,9 +142914,11 @@ static const char *columnTypeImpl(
** statement.
*/
NameContext sNC;
- Select *pS = pExpr->x.pSelect;
- Expr *p = pS->pEList->a[0].pExpr;
- assert( ExprHasProperty(pExpr, EP_xIsSelect) );
+ Select *pS;
+ Expr *p;
+ assert( ExprUseXSelect(pExpr) );
+ pS = pExpr->x.pSelect;
+ p = pS->pEList->a[0].pExpr;
sNC.pSrcList = pS->pSrc;
sNC.pNext = pNC;
sNC.pParse = pNC->pParse;
@@ -136536,7 +143010,7 @@ static void generateColumnTypes(
** then the result column name with the table name
** prefix, ex: TABLE.COLUMN. Otherwise use zSpan.
*/
-static void generateColumnNames(
+SQLITE_PRIVATE void sqlcipher_sqlite3GenerateColumnNames(
Parse *pParse, /* Parser context */
Select *pSelect /* Generate column names for this SELECT statement */
){
@@ -136573,8 +143047,9 @@ static void generateColumnNames(
assert( p!=0 );
assert( p->op!=TK_AGG_COLUMN ); /* Agg processing has not run yet */
- assert( p->op!=TK_COLUMN || p->y.pTab!=0 ); /* Covering idx not yet coded */
- if( pEList->a[i].zEName && pEList->a[i].eEName==ENAME_NAME ){
+ assert( p->op!=TK_COLUMN
+ || (ExprUseYTab(p) && p->y.pTab!=0) ); /* Covering idx not yet coded */
+ if( pEList->a[i].zEName && pEList->a[i].fg.eEName==ENAME_NAME ){
/* An AS clause always takes first priority */
char *zName = pEList->a[i].zEName;
sqlcipher_sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_TRANSIENT);
@@ -136588,7 +143063,7 @@ static void generateColumnNames(
if( iCol<0 ){
zCol = "rowid";
}else{
- zCol = pTab->aCol[iCol].zName;
+ zCol = pTab->aCol[iCol].zCnName;
}
if( fullName ){
char *zName = 0;
@@ -136626,7 +143101,7 @@ static void generateColumnNames(
** and will break if those assumptions changes. Hence, use extreme caution
** when modifying this routine to avoid breaking legacy.
**
-** See Also: generateColumnNames()
+** See Also: sqlcipher_sqlite3GenerateColumnNames()
*/
SQLITE_PRIVATE int sqlcipher_sqlite3ColumnsFromExprList(
Parse *pParse, /* Parsing context */
@@ -136649,7 +143124,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ColumnsFromExprList(
nCol = pEList->nExpr;
aCol = sqlcipher_sqlite3DbMallocZero(db, sizeof(aCol[0])*nCol);
testcase( aCol==0 );
- if( nCol>32767 ) nCol = 32767;
+ if( NEVER(nCol>32767) ) nCol = 32767;
}else{
nCol = 0;
aCol = 0;
@@ -136659,27 +143134,33 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ColumnsFromExprList(
*paCol = aCol;
for(i=0, pCol=aCol; i<nCol && !db->mallocFailed; i++, pCol++){
+ struct ExprList_item *pX = &pEList->a[i];
+ struct ExprList_item *pCollide;
/* Get an appropriate name for the column
*/
- if( (zName = pEList->a[i].zEName)!=0 && pEList->a[i].eEName==ENAME_NAME ){
+ if( (zName = pX->zEName)!=0 && pX->fg.eEName==ENAME_NAME ){
/* If the column contains an "AS <name>" phrase, use <name> as the name */
}else{
- Expr *pColExpr = sqlcipher_sqlite3ExprSkipCollateAndLikely(pEList->a[i].pExpr);
+ Expr *pColExpr = sqlcipher_sqlite3ExprSkipCollateAndLikely(pX->pExpr);
while( ALWAYS(pColExpr!=0) && pColExpr->op==TK_DOT ){
pColExpr = pColExpr->pRight;
assert( pColExpr!=0 );
}
- if( pColExpr->op==TK_COLUMN && (pTab = pColExpr->y.pTab)!=0 ){
+ if( pColExpr->op==TK_COLUMN
+ && ALWAYS( ExprUseYTab(pColExpr) )
+ && ALWAYS( pColExpr->y.pTab!=0 )
+ ){
/* For columns use the column name name */
int iCol = pColExpr->iColumn;
+ pTab = pColExpr->y.pTab;
if( iCol<0 ) iCol = pTab->iPKey;
- zName = iCol>=0 ? pTab->aCol[iCol].zName : "rowid";
+ zName = iCol>=0 ? pTab->aCol[iCol].zCnName : "rowid";
}else if( pColExpr->op==TK_ID ){
assert( !ExprHasProperty(pColExpr, EP_IntValue) );
zName = pColExpr->u.zToken;
}else{
/* Use the original text of the column expression as its name */
- zName = pEList->a[i].zEName;
+ assert( zName==pX->zEName ); /* pointer comparison intended */
}
}
if( zName && !sqlcipher_sqlite3IsTrueOrFalse(zName) ){
@@ -136692,7 +143173,10 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ColumnsFromExprList(
** append an integer to the name so that it becomes unique.
*/
cnt = 0;
- while( zName && sqlcipher_sqlite3HashFind(&ht, zName)!=0 ){
+ while( zName && (pCollide = sqlcipher_sqlite3HashFind(&ht, zName))!=0 ){
+ if( pCollide->fg.bUsingTerm ){
+ pCol->colFlags |= COLFLAG_NOEXPAND;
+ }
nName = sqlcipher_sqlite3Strlen30(zName);
if( nName>0 ){
for(j=nName-1; j>0 && sqlcipher_sqlite3Isdigit(zName[j]); j--){}
@@ -136701,17 +143185,20 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ColumnsFromExprList(
zName = sqlcipher_sqlite3MPrintf(db, "%.*z:%u", nName, zName, ++cnt);
if( cnt>3 ) sqlcipher_sqlite3_randomness(sizeof(cnt), &cnt);
}
- pCol->zName = zName;
+ pCol->zCnName = zName;
pCol->hName = sqlcipher_sqlite3StrIHash(zName);
+ if( pX->fg.bNoExpand ){
+ pCol->colFlags |= COLFLAG_NOEXPAND;
+ }
sqlcipher_sqlite3ColumnPropertiesFromName(0, pCol);
- if( zName && sqlcipher_sqlite3HashInsert(&ht, zName, pCol)==pCol ){
+ if( zName && sqlcipher_sqlite3HashInsert(&ht, zName, pX)==pX ){
sqlcipher_sqlite3OomFault(db);
}
}
sqlcipher_sqlite3HashClear(&ht);
if( db->mallocFailed ){
for(j=0; j<i; j++){
- sqlcipher_sqlite3DbFree(db, aCol[j].zName);
+ sqlcipher_sqlite3DbFree(db, aCol[j].zCnName);
}
sqlcipher_sqlite3DbFree(db, aCol);
*paCol = 0;
@@ -136755,24 +143242,29 @@ SQLITE_PRIVATE void sqlcipher_sqlite3SelectAddColumnTypeAndCollation(
a = pSelect->pEList->a;
for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
const char *zType;
- int n, m;
+ i64 n, m;
+ pTab->tabFlags |= (pCol->colFlags & COLFLAG_NOINSERT);
p = a[i].pExpr;
zType = columnType(&sNC, p, 0, 0, 0);
/* pCol->szEst = ... // Column size est for SELECT tables never used */
pCol->affinity = sqlcipher_sqlite3ExprAffinity(p);
if( zType ){
m = sqlcipher_sqlite3Strlen30(zType);
- n = sqlcipher_sqlite3Strlen30(pCol->zName);
- pCol->zName = sqlcipher_sqlite3DbReallocOrFree(db, pCol->zName, n+m+2);
- if( pCol->zName ){
- memcpy(&pCol->zName[n+1], zType, m+1);
+ n = sqlcipher_sqlite3Strlen30(pCol->zCnName);
+ pCol->zCnName = sqlcipher_sqlite3DbReallocOrFree(db, pCol->zCnName, n+m+2);
+ if( pCol->zCnName ){
+ memcpy(&pCol->zCnName[n+1], zType, m+1);
pCol->colFlags |= COLFLAG_HASTYPE;
+ }else{
+ testcase( pCol->colFlags & COLFLAG_HASTYPE );
+ pCol->colFlags &= ~(COLFLAG_HASTYPE|COLFLAG_HASCOLL);
}
}
if( pCol->affinity<=SQLITE_AFF_NONE ) pCol->affinity = aff;
pColl = sqlcipher_sqlite3ExprCollSeq(pParse, p);
- if( pColl && pCol->zColl==0 ){
- pCol->zColl = sqlcipher_sqlite3DbStrDup(db, pColl->zName);
+ if( pColl ){
+ assert( pTab->pIndex==0 );
+ sqlcipher_sqlite3ColumnSetColl(db, pCol, pColl->zName);
}
}
pTab->szTabRow = 1; /* Any non-zero value works */
@@ -136936,7 +143428,7 @@ static CollSeq *multiSelectCollSeq(Parse *pParse, Select *p, int iCol){
*/
static KeyInfo *multiSelectOrderByKeyInfo(Parse *pParse, Select *p, int nExtra){
ExprList *pOrderBy = p->pOrderBy;
- int nOrderBy = p->pOrderBy->nExpr;
+ int nOrderBy = ALWAYS(pOrderBy!=0) ? pOrderBy->nExpr : 0;
sqlcipher_sqlite3 *db = pParse->db;
KeyInfo *pRet = sqlcipher_sqlite3KeyInfoAlloc(db, nOrderBy+nExtra, 1);
if( pRet ){
@@ -136956,7 +143448,7 @@ static KeyInfo *multiSelectOrderByKeyInfo(Parse *pParse, Select *p, int nExtra){
}
assert( sqlcipher_sqlite3KeyInfoIsWriteable(pRet) );
pRet->aColl[i] = pColl;
- pRet->aSortFlags[i] = pOrderBy->a[i].sortFlags;
+ pRet->aSortFlags[i] = pOrderBy->a[i].fg.sortFlags;
}
}
@@ -137008,7 +143500,7 @@ static void generateWithRecursiveQuery(
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 */
+ Select *pSetup; /* The setup query */
Select *pFirstRec; /* Left-most recursive term */
int addrTop; /* Top of the loop */
int addrCont, addrBreak; /* CONTINUE and BREAK addresses */
@@ -137092,7 +143584,6 @@ static void generateWithRecursiveQuery(
** iDistinct table. pFirstRec is left pointing to the left-most
** recursive term of the CTE.
*/
- pFirstRec = p;
for(pFirstRec=p; ALWAYS(pFirstRec!=0); pFirstRec=pFirstRec->pPrior){
if( pFirstRec->selFlags & SF_Aggregate ){
sqlcipher_sqlite3ErrorMsg(pParse, "recursive aggregate queries not supported");
@@ -137175,7 +143666,7 @@ static int multiSelectOrderBy(
** The "LIMIT of exactly 1" case of condition (1) comes about when a VALUES
** clause occurs within scalar expression (ex: "SELECT (VALUES(1),(2),(3))").
** The sqlcipher_sqlite3CodeSubselect will have added the LIMIT 1 clause in tht case.
-** Since the limit is exactly 1, we only need to evalutes the left-most VALUES.
+** Since the limit is exactly 1, we only need to evaluate the left-most VALUES.
*/
static int multiSelectValues(
Parse *pParse, /* Parsing context */
@@ -137271,12 +143762,8 @@ static int multiSelect(
db = pParse->db;
pPrior = p->pPrior;
dest = *pDest;
- if( pPrior->pOrderBy || pPrior->pLimit ){
- sqlcipher_sqlite3ErrorMsg(pParse,"%s clause should come after %s not before",
- pPrior->pOrderBy!=0 ? "ORDER BY" : "LIMIT", selectOpName(p->op));
- rc = 1;
- goto multi_select_end;
- }
+ assert( pPrior->pOrderBy==0 );
+ assert( pPrior->pLimit==0 );
v = sqlcipher_sqlite3GetVdbe(pParse);
assert( v!=0 ); /* The VDBE already created by calling function */
@@ -137327,13 +143814,14 @@ static int multiSelect(
switch( p->op ){
case TK_ALL: {
int addr = 0;
- int nLimit;
+ int nLimit = 0; /* Initialize to suppress harmless compiler warning */
assert( !pPrior->pLimit );
pPrior->iLimit = p->iLimit;
pPrior->iOffset = p->iOffset;
pPrior->pLimit = p->pLimit;
+ SELECTTRACE(1, pParse, p, ("multiSelect UNION ALL left...\n"));
rc = sqlcipher_sqlite3Select(pParse, pPrior, &dest);
- p->pLimit = 0;
+ pPrior->pLimit = 0;
if( rc ){
goto multi_select_end;
}
@@ -137349,13 +143837,14 @@ static int multiSelect(
}
}
ExplainQueryPlan((pParse, 1, "UNION ALL"));
+ SELECTTRACE(1, pParse, p, ("multiSelect UNION ALL right...\n"));
rc = sqlcipher_sqlite3Select(pParse, p, &dest);
testcase( rc!=SQLITE_OK );
pDelete = p->pPrior;
p->pPrior = pPrior;
p->nSelectRow = sqlcipher_sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
- if( pPrior->pLimit
- && sqlcipher_sqlite3ExprIsInteger(pPrior->pLimit->pLeft, &nLimit)
+ if( p->pLimit
+ && sqlcipher_sqlite3ExprIsInteger(p->pLimit->pLeft, &nLimit)
&& nLimit>0 && p->nSelectRow > sqlcipher_sqlite3LogEst((u64)nLimit)
){
p->nSelectRow = sqlcipher_sqlite3LogEst((u64)nLimit);
@@ -137401,6 +143890,7 @@ static int multiSelect(
*/
assert( !pPrior->pOrderBy );
sqlcipher_sqlite3SelectDestInit(&uniondest, priorOp, unionTab);
+ SELECTTRACE(1, pParse, p, ("multiSelect EXCEPT/UNION left...\n"));
rc = sqlcipher_sqlite3Select(pParse, pPrior, &uniondest);
if( rc ){
goto multi_select_end;
@@ -137419,7 +143909,8 @@ static int multiSelect(
p->pLimit = 0;
uniondest.eDest = op;
ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE",
- selectOpName(p->op)));
+ sqlcipher_sqlite3SelectOpName(p->op)));
+ SELECTTRACE(1, pParse, p, ("multiSelect EXCEPT/UNION right...\n"));
rc = sqlcipher_sqlite3Select(pParse, p, &uniondest);
testcase( rc!=SQLITE_OK );
assert( p->pOrderBy==0 );
@@ -137480,6 +143971,7 @@ static int multiSelect(
/* Code the SELECTs to our left into temporary table "tab1".
*/
sqlcipher_sqlite3SelectDestInit(&intersectdest, SRT_Union, tab1);
+ SELECTTRACE(1, pParse, p, ("multiSelect INTERSECT left...\n"));
rc = sqlcipher_sqlite3Select(pParse, pPrior, &intersectdest);
if( rc ){
goto multi_select_end;
@@ -137495,7 +143987,8 @@ static int multiSelect(
p->pLimit = 0;
intersectdest.iSDParm = tab2;
ExplainQueryPlan((pParse, 1, "%s USING TEMP B-TREE",
- selectOpName(p->op)));
+ sqlcipher_sqlite3SelectOpName(p->op)));
+ SELECTTRACE(1, pParse, p, ("multiSelect INTERSECT right...\n"));
rc = sqlcipher_sqlite3Select(pParse, p, &intersectdest);
testcase( rc!=SQLITE_OK );
pDelete = p->pPrior;
@@ -137556,6 +144049,7 @@ static int multiSelect(
int nCol; /* Number of columns in result set */
assert( p->pNext==0 );
+ assert( p->pEList!=0 );
nCol = p->pEList->nExpr;
pKeyInfo = sqlcipher_sqlite3KeyInfoAlloc(db, nCol, 1);
if( !pKeyInfo ){
@@ -137590,7 +144084,11 @@ static int multiSelect(
multi_select_end:
pDest->iSdst = dest.iSdst;
pDest->nSdst = dest.nSdst;
- sqlcipher_sqlite3SelectDelete(db, pDelete);
+ if( pDelete ){
+ sqlcipher_sqlite3ParserAddCleanup(pParse,
+ (void(*)(sqlcipher_sqlite3*,void*))sqlcipher_sqlite3SelectDelete,
+ pDelete);
+ }
return rc;
}
#endif /* SQLITE_OMIT_COMPOUND_SELECT */
@@ -137604,7 +144102,8 @@ SQLITE_PRIVATE void sqlcipher_sqlite3SelectWrongNumTermsError(Parse *pParse, Sel
sqlcipher_sqlite3ErrorMsg(pParse, "all VALUES must have the same number of terms");
}else{
sqlcipher_sqlite3ErrorMsg(pParse, "SELECTs to the left and right of %s"
- " do not have the same number of result columns", selectOpName(p->op));
+ " do not have the same number of result columns",
+ sqlcipher_sqlite3SelectOpName(p->op));
}
}
@@ -137701,10 +144200,8 @@ static int generateOutputSubroutine(
** if it is the RHS of a row-value IN operator.
*/
case SRT_Mem: {
- if( pParse->nErr==0 ){
- testcase( pIn->nSdst>1 );
- sqlcipher_sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSDParm, pIn->nSdst);
- }
+ testcase( pIn->nSdst>1 );
+ sqlcipher_sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSDParm, pIn->nSdst);
/* The LIMIT clause will jump out of the loop for us */
break;
}
@@ -137845,6 +144342,8 @@ static int multiSelectOrderBy(
){
int i, j; /* Loop counters */
Select *pPrior; /* Another SELECT immediately to our left */
+ Select *pSplit; /* Left-most SELECT in the right-hand group */
+ int nSelect; /* Number of SELECT statements in the compound */
Vdbe *v; /* Generate code to this VDBE */
SelectDest destA; /* Destination for coroutine A */
SelectDest destB; /* Destination for coroutine B */
@@ -137890,8 +144389,7 @@ static int multiSelectOrderBy(
/* Patch up the ORDER BY clause
*/
op = p->op;
- pPrior = p->pPrior;
- assert( pPrior->pOrderBy==0 );
+ assert( p->pPrior->pOrderBy==0 );
pOrderBy = p->pOrderBy;
assert( pOrderBy );
nOrderBy = pOrderBy->nExpr;
@@ -137904,6 +144402,7 @@ 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!=0 );
assert( pItem->u.x.iOrderByCol>0 );
if( pItem->u.x.iOrderByCol==i ) break;
}
@@ -137930,6 +144429,7 @@ static int multiSelectOrderBy(
struct ExprList_item *pItem;
aPermute[0] = nOrderBy;
for(i=1, pItem=pOrderBy->a; i<=nOrderBy; i++, pItem++){
+ assert( pItem!=0 );
assert( pItem->u.x.iOrderByCol>0 );
assert( pItem->u.x.iOrderByCol<=p->pEList->nExpr );
aPermute[i] = pItem->u.x.iOrderByCol - 1;
@@ -137939,11 +144439,6 @@ static int multiSelectOrderBy(
pKeyMerge = 0;
}
- /* Reattach the ORDER BY clause to the query.
- */
- p->pOrderBy = pOrderBy;
- pPrior->pOrderBy = sqlcipher_sqlite3ExprListDup(pParse->db, pOrderBy, 0);
-
/* Allocate a range of temporary registers and the KeyInfo needed
** for the logic that removes duplicate result rows when the
** operator is UNION, EXCEPT, or INTERSECT (but not UNION ALL).
@@ -137968,12 +144463,30 @@ static int multiSelectOrderBy(
/* Separate the left and the right query from one another
*/
- p->pPrior = 0;
+ nSelect = 1;
+ if( (op==TK_ALL || op==TK_UNION)
+ && OptimizationEnabled(db, SQLITE_BalancedMerge)
+ ){
+ for(pSplit=p; pSplit->pPrior!=0 && pSplit->op==op; pSplit=pSplit->pPrior){
+ nSelect++;
+ assert( pSplit->pPrior->pNext==pSplit );
+ }
+ }
+ if( nSelect<=3 ){
+ pSplit = p;
+ }else{
+ pSplit = p;
+ for(i=2; i<nSelect; i+=2){ pSplit = pSplit->pPrior; }
+ }
+ pPrior = pSplit->pPrior;
+ assert( pPrior!=0 );
+ pSplit->pPrior = 0;
pPrior->pNext = 0;
+ assert( p->pOrderBy == pOrderBy );
+ assert( pOrderBy!=0 || db->mallocFailed );
+ pPrior->pOrderBy = sqlcipher_sqlite3ExprListDup(pParse->db, pOrderBy, 0);
sqlcipher_sqlite3ResolveOrderGroupBy(pParse, p, p->pOrderBy, "ORDER");
- if( pPrior->pPrior==0 ){
- sqlcipher_sqlite3ResolveOrderGroupBy(pParse, pPrior, pPrior->pOrderBy, "ORDER");
- }
+ sqlcipher_sqlite3ResolveOrderGroupBy(pParse, pPrior, pPrior->pOrderBy, "ORDER");
/* Compute the limit registers */
computeLimitRegisters(pParse, p, labelEnd);
@@ -137996,7 +144509,7 @@ static int multiSelectOrderBy(
sqlcipher_sqlite3SelectDestInit(&destA, SRT_Coroutine, regAddrA);
sqlcipher_sqlite3SelectDestInit(&destB, SRT_Coroutine, regAddrB);
- ExplainQueryPlan((pParse, 1, "MERGE (%s)", selectOpName(p->op)));
+ ExplainQueryPlan((pParse, 1, "MERGE (%s)", sqlcipher_sqlite3SelectOpName(p->op)));
/* Generate a coroutine to evaluate the SELECT statement to the
** left of the compound operator - the "A" select.
@@ -138122,13 +144635,16 @@ static int multiSelectOrderBy(
*/
sqlcipher_sqlite3VdbeResolveLabel(v, labelEnd);
- /* Reassembly the compound query so that it will be freed correctly
+ /* Reassemble the compound query so that it will be freed correctly
** by the calling function */
- if( p->pPrior ){
- sqlcipher_sqlite3SelectDelete(db, p->pPrior);
+ if( pSplit->pPrior ){
+ sqlcipher_sqlite3ParserAddCleanup(pParse,
+ (void(*)(sqlcipher_sqlite3*,void*))sqlcipher_sqlite3SelectDelete, pSplit->pPrior);
}
- p->pPrior = pPrior;
- pPrior->pNext = p;
+ pSplit->pPrior = pPrior;
+ pPrior->pNext = pSplit;
+ sqlcipher_sqlite3ExprListDelete(db, pPrior->pOrderBy);
+ pPrior->pOrderBy = 0;
/*** TBD: Insert subroutine calls to close cursors on incomplete
**** subqueries ****/
@@ -138144,12 +144660,40 @@ static int multiSelectOrderBy(
**
** All references to columns in table iTable are to be replaced by corresponding
** expressions in pEList.
+**
+** ## About "isOuterJoin":
+**
+** The isOuterJoin column indicates that the replacement will occur into a
+** position in the parent that NULL-able due to an OUTER JOIN. Either the
+** target slot in the parent is the right operand of a LEFT JOIN, or one of
+** the left operands of a RIGHT JOIN. In either case, we need to potentially
+** bypass the substituted expression with OP_IfNullRow.
+**
+** Suppose the original expression integer constant. Even though the table
+** has the nullRow flag set, because the expression is an integer constant,
+** it will not be NULLed out. So instead, we insert an OP_IfNullRow opcode
+** that checks to see if the nullRow flag is set on the table. If the nullRow
+** flag is set, then the value in the register is set to NULL and the original
+** expression is bypassed. If the nullRow flag is not set, then the original
+** expression runs to populate the register.
+**
+** Example where this is needed:
+**
+** CREATE TABLE t1(a INTEGER PRIMARY KEY, b INT);
+** CREATE TABLE t2(x INT UNIQUE);
+**
+** SELECT a,b,m,x FROM t1 LEFT JOIN (SELECT 59 AS m,x FROM t2) ON b=x;
+**
+** When the subquery on the right side of the LEFT JOIN is flattened, we
+** have to add OP_IfNullRow in front of the OP_Integer that implements the
+** "m" value of the subquery so that a NULL will be loaded instead of 59
+** when processing a non-matched row of the left.
*/
typedef struct SubstContext {
Parse *pParse; /* The parsing context */
int iTable; /* Replace references to this table */
int iNewTable; /* New table number */
- int isLeftJoin; /* Add TK_IF_NULL_ROW opcodes on each replacement */
+ int isOuterJoin; /* Add TK_IF_NULL_ROW opcodes on each replacement */
ExprList *pEList; /* Replacement expressions */
} SubstContext;
@@ -138175,18 +144719,22 @@ static Expr *substExpr(
Expr *pExpr /* Expr in which substitution occurs */
){
if( pExpr==0 ) return 0;
- if( ExprHasProperty(pExpr, EP_FromJoin)
- && pExpr->iRightJoinTable==pSubst->iTable
+ if( ExprHasProperty(pExpr, EP_OuterON|EP_InnerON)
+ && pExpr->w.iJoin==pSubst->iTable
){
- pExpr->iRightJoinTable = pSubst->iNewTable;
+ testcase( ExprHasProperty(pExpr, EP_InnerON) );
+ pExpr->w.iJoin = pSubst->iNewTable;
}
if( pExpr->op==TK_COLUMN
&& pExpr->iTable==pSubst->iTable
&& !ExprHasProperty(pExpr, EP_FixedCol)
){
+#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
if( pExpr->iColumn<0 ){
pExpr->op = TK_NULL;
- }else{
+ }else
+#endif
+ {
Expr *pNew;
Expr *pCopy = pSubst->pEList->a[pExpr->iColumn].pExpr;
Expr ifNullRow;
@@ -138196,7 +144744,7 @@ static Expr *substExpr(
sqlcipher_sqlite3VectorErrorMsg(pSubst->pParse, pCopy);
}else{
sqlcipher_sqlite3 *db = pSubst->pParse->db;
- if( pSubst->isLeftJoin && pCopy->op!=TK_COLUMN ){
+ if( pSubst->isOuterJoin && pCopy->op!=TK_COLUMN ){
memset(&ifNullRow, 0, sizeof(ifNullRow));
ifNullRow.op = TK_IF_NULL_ROW;
ifNullRow.pLeft = pCopy;
@@ -138206,26 +144754,34 @@ static Expr *substExpr(
}
testcase( ExprHasProperty(pCopy, EP_Subquery) );
pNew = sqlcipher_sqlite3ExprDup(db, pCopy, 0);
- if( pNew && pSubst->isLeftJoin ){
+ if( db->mallocFailed ){
+ sqlcipher_sqlite3ExprDelete(db, pNew);
+ return pExpr;
+ }
+ if( pSubst->isOuterJoin ){
ExprSetProperty(pNew, EP_CanBeNull);
}
- if( pNew && ExprHasProperty(pExpr,EP_FromJoin) ){
- sqlcipher_sqlite3SetJoinExpr(pNew, pExpr->iRightJoinTable);
+ if( ExprHasProperty(pExpr,EP_OuterON|EP_InnerON) ){
+ sqlcipher_sqlite3SetJoinExpr(pNew, pExpr->w.iJoin,
+ pExpr->flags & (EP_OuterON|EP_InnerON));
}
sqlcipher_sqlite3ExprDelete(db, pExpr);
pExpr = pNew;
+ if( pExpr->op==TK_TRUEFALSE ){
+ pExpr->u.iValue = sqlcipher_sqlite3ExprTruthValue(pExpr);
+ pExpr->op = TK_INTEGER;
+ ExprSetProperty(pExpr, EP_IntValue);
+ }
/* Ensure that the expression now has an implicit collation sequence,
** just as it did when it was a column of a view or sub-query. */
- if( pExpr ){
- if( pExpr->op!=TK_COLUMN && pExpr->op!=TK_COLLATE ){
- CollSeq *pColl = sqlcipher_sqlite3ExprCollSeq(pSubst->pParse, pExpr);
- pExpr = sqlcipher_sqlite3ExprAddCollateString(pSubst->pParse, pExpr,
- (pColl ? pColl->zName : "BINARY")
- );
- }
- ExprClearProperty(pExpr, EP_Collate);
+ if( pExpr->op!=TK_COLUMN && pExpr->op!=TK_COLLATE ){
+ CollSeq *pColl = sqlcipher_sqlite3ExprCollSeq(pSubst->pParse, pExpr);
+ pExpr = sqlcipher_sqlite3ExprAddCollateString(pSubst->pParse, pExpr,
+ (pColl ? pColl->zName : "BINARY")
+ );
}
+ ExprClearProperty(pExpr, EP_Collate);
}
}
}else{
@@ -138234,7 +144790,7 @@ static Expr *substExpr(
}
pExpr->pLeft = substExpr(pSubst, pExpr->pLeft);
pExpr->pRight = substExpr(pSubst, pExpr->pRight);
- if( ExprHasProperty(pExpr, EP_xIsSelect) ){
+ if( ExprUseXSelect(pExpr) ){
substSelect(pSubst, pExpr->x.pSelect, 1);
}else{
substExprList(pSubst, pExpr->x.pList);
@@ -138266,7 +144822,7 @@ static void substSelect(
int doPrior /* Do substitutes on p->pPrior too */
){
SrcList *pSrc;
- struct SrcList_item *pItem;
+ SrcItem *pItem;
int i;
if( !p ) return;
do{
@@ -138296,7 +144852,7 @@ static void substSelect(
** pSrcItem->colUsed mask.
*/
static int recomputeColumnsUsedExpr(Walker *pWalker, Expr *pExpr){
- struct SrcList_item *pItem;
+ SrcItem *pItem;
if( pExpr->op!=TK_COLUMN ) return WRC_Continue;
pItem = pWalker->u.pSrcItem;
if( pItem->iCursor!=pExpr->iTable ) return WRC_Continue;
@@ -138306,7 +144862,7 @@ static int recomputeColumnsUsedExpr(Walker *pWalker, Expr *pExpr){
}
static void recomputeColumnsUsed(
Select *pSelect, /* The complete SELECT statement */
- struct SrcList_item *pSrcItem /* Which FROM clause item to recompute */
+ SrcItem *pSrcItem /* Which FROM clause item to recompute */
){
Walker w;
if( NEVER(pSrcItem->pTab==0) ) return;
@@ -138321,6 +144877,103 @@ static void recomputeColumnsUsed(
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
/*
+** Assign new cursor numbers to each of the items in pSrc. For each
+** new cursor number assigned, set an entry in the aCsrMap[] array
+** to map the old cursor number to the new:
+**
+** aCsrMap[iOld+1] = iNew;
+**
+** The array is guaranteed by the caller to be large enough for all
+** existing cursor numbers in pSrc. aCsrMap[0] is the array size.
+**
+** If pSrc contains any sub-selects, call this routine recursively
+** on the FROM clause of each such sub-select, with iExcept set to -1.
+*/
+static void srclistRenumberCursors(
+ Parse *pParse, /* Parse context */
+ int *aCsrMap, /* Array to store cursor mappings in */
+ SrcList *pSrc, /* FROM clause to renumber */
+ int iExcept /* FROM clause item to skip */
+){
+ int i;
+ SrcItem *pItem;
+ for(i=0, pItem=pSrc->a; i<pSrc->nSrc; i++, pItem++){
+ if( i!=iExcept ){
+ Select *p;
+ assert( pItem->iCursor < aCsrMap[0] );
+ if( !pItem->fg.isRecursive || aCsrMap[pItem->iCursor+1]==0 ){
+ aCsrMap[pItem->iCursor+1] = pParse->nTab++;
+ }
+ pItem->iCursor = aCsrMap[pItem->iCursor+1];
+ for(p=pItem->pSelect; p; p=p->pPrior){
+ srclistRenumberCursors(pParse, aCsrMap, p->pSrc, -1);
+ }
+ }
+ }
+}
+
+/*
+** *piCursor is a cursor number. Change it if it needs to be mapped.
+*/
+static void renumberCursorDoMapping(Walker *pWalker, int *piCursor){
+ int *aCsrMap = pWalker->u.aiCol;
+ int iCsr = *piCursor;
+ if( iCsr < aCsrMap[0] && aCsrMap[iCsr+1]>0 ){
+ *piCursor = aCsrMap[iCsr+1];
+ }
+}
+
+/*
+** Expression walker callback used by renumberCursors() to update
+** Expr objects to match newly assigned cursor numbers.
+*/
+static int renumberCursorsCb(Walker *pWalker, Expr *pExpr){
+ int op = pExpr->op;
+ if( op==TK_COLUMN || op==TK_IF_NULL_ROW ){
+ renumberCursorDoMapping(pWalker, &pExpr->iTable);
+ }
+ if( ExprHasProperty(pExpr, EP_OuterON) ){
+ renumberCursorDoMapping(pWalker, &pExpr->w.iJoin);
+ }
+ return WRC_Continue;
+}
+
+/*
+** Assign a new cursor number to each cursor in the FROM clause (Select.pSrc)
+** of the SELECT statement passed as the second argument, and to each
+** cursor in the FROM clause of any FROM clause sub-selects, recursively.
+** Except, do not assign a new cursor number to the iExcept'th element in
+** the FROM clause of (*p). Update all expressions and other references
+** to refer to the new cursor numbers.
+**
+** Argument aCsrMap is an array that may be used for temporary working
+** space. Two guarantees are made by the caller:
+**
+** * the array is larger than the largest cursor number used within the
+** select statement passed as an argument, and
+**
+** * the array entries for all cursor numbers that do *not* appear in
+** FROM clauses of the select statement as described above are
+** initialized to zero.
+*/
+static void renumberCursors(
+ Parse *pParse, /* Parse context */
+ Select *p, /* Select to renumber cursors within */
+ int iExcept, /* FROM clause item to skip */
+ int *aCsrMap /* Working space */
+){
+ Walker w;
+ srclistRenumberCursors(pParse, aCsrMap, p->pSrc, iExcept);
+ memset(&w, 0, sizeof(w));
+ w.u.aiCol = aCsrMap;
+ w.xExprCallback = renumberCursorsCb;
+ w.xSelectCallback = sqlcipher_sqlite3SelectWalkNoop;
+ sqlcipher_sqlite3WalkSelect(&w, p);
+}
+#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
+
+#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
+/*
** This routine attempts to flatten subqueries as a performance optimization.
** This routine returns 1 if it makes changes and 0 if no flattening occurs.
**
@@ -138365,6 +145018,7 @@ static void recomputeColumnsUsed(
** table and
** (3c) the outer query may not be an aggregate.
** (3d) the outer query may not be DISTINCT.
+** See also (26) for restrictions on RIGHT JOIN.
**
** (4) The subquery can not be DISTINCT.
**
@@ -138413,9 +145067,12 @@ static void recomputeColumnsUsed(
** (17c) every term within the subquery compound must have a FROM clause
** (17d) the outer query may not be
** (17d1) aggregate, or
-** (17d2) DISTINCT, or
-** (17d3) a join.
-** (17e) the subquery may not contain window functions
+** (17d2) DISTINCT
+** (17e) the subquery may not contain window functions, and
+** (17f) the subquery must not be the RHS of a LEFT JOIN.
+** (17g) either the subquery is the first element of the outer
+** query or there are no RIGHT or FULL JOINs in any arm
+** of the subquery. (This is a duplicate of condition (27b).)
**
** The parent and sub-query may contain WHERE clauses. Subject to
** rules (11), (13) and (14), they may also contain ORDER BY,
@@ -138431,8 +145088,8 @@ static void recomputeColumnsUsed(
** syntax error and return a detailed message.
**
** (18) If the sub-query is a compound select, then all terms of the
-** ORDER BY clause of the parent must be simple references to
-** columns of the sub-query.
+** ORDER BY clause of the parent must be copies of a term returned
+** by the parent query.
**
** (19) If the subquery uses LIMIT then the outer query may not
** have a WHERE clause.
@@ -138448,9 +145105,8 @@ static void recomputeColumnsUsed(
**
** (22) The subquery may not be a recursive CTE.
**
-** (**) Subsumed into restriction (17d3). Was: If the outer query is
-** a recursive CTE, then the sub-query may not be a compound query.
-** This restriction is because transforming the
+** (23) If the outer query is a recursive CTE, then the sub-query may not be
+** a compound query. This restriction is because transforming the
** parent to a compound query confuses the code that handles
** recursive queries in multiSelect().
**
@@ -138464,6 +145120,23 @@ static void recomputeColumnsUsed(
** function in the select list or ORDER BY clause, flattening
** is not attempted.
**
+** (26) The subquery may not be the right operand of a RIGHT JOIN.
+** See also (3) for restrictions on LEFT JOIN.
+**
+** (27) The subquery may not contain a FULL or RIGHT JOIN unless it
+** is the first element of the parent query. This must be the
+** the case if:
+** (27a) the subquery is not compound query, and
+** (27b) the subquery is a compound query and the RIGHT JOIN occurs
+** in any arm of the compound query. (See also (17g).)
+**
+** (28) The subquery is not a MATERIALIZED CTE.
+**
+** (29) Either the subquery is not the right-hand operand of a join with an
+** ON or USING clause nor the right-hand operand of a NATURAL JOIN, or
+** the right-most table within the FROM clause of the subquery
+** is not part of an outer join.
+**
**
** 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
@@ -138489,12 +145162,13 @@ static int flattenSubquery(
SrcList *pSubSrc; /* The FROM clause of the subquery */
int iParent; /* VDBE cursor number of the pSub result set temp table */
int iNewParent = -1;/* Replacement table for iParent */
- int isLeftJoin = 0; /* True if pSub is the right side of a LEFT JOIN */
+ int isOuterJoin = 0; /* True if pSub is the right side of a LEFT JOIN */
int i; /* Loop counter */
Expr *pWhere; /* The WHERE clause */
- struct SrcList_item *pSubitem; /* The subquery */
+ SrcItem *pSubitem; /* The subquery */
sqlcipher_sqlite3 *db = pParse->db;
Walker w; /* Walker to persist agginfo data */
+ int *aCsrMap = 0;
/* Check to see if flattening is permitted. Return 0 if not.
*/
@@ -138561,26 +145235,64 @@ static int flattenSubquery(
**
** See also tickets #306, #350, and #3300.
*/
- if( (pSubitem->fg.jointype & JT_OUTER)!=0 ){
- isLeftJoin = 1;
- if( pSubSrc->nSrc>1 /* (3a) */
- || isAgg /* (3b) */
- || IsVirtual(pSubSrc->a[0].pTab) /* (3c) */
- || (p->selFlags & SF_Distinct)!=0 /* (3d) */
+ if( (pSubitem->fg.jointype & (JT_OUTER|JT_LTORJ))!=0 ){
+ if( pSubSrc->nSrc>1 /* (3a) */
+ || isAgg /* (3c) */
+ || IsVirtual(pSubSrc->a[0].pTab) /* (3b) */
+ || (p->selFlags & SF_Distinct)!=0 /* (3d) */
+ || (pSubitem->fg.jointype & JT_RIGHT)!=0 /* (26) */
){
return 0;
}
+ isOuterJoin = 1;
}
#ifdef SQLITE_EXTRA_IFNULLROW
else if( iFrom>0 && !isAgg ){
- /* Setting isLeftJoin to -1 causes OP_IfNullRow opcodes to be generated for
+ /* Setting isOuterJoin to -1 causes OP_IfNullRow opcodes to be generated for
** every reference to any result column from subquery in a join, even
** though they are not necessary. This will stress-test the OP_IfNullRow
** opcode. */
- isLeftJoin = -1;
+ isOuterJoin = -1;
}
#endif
+ assert( pSubSrc->nSrc>0 ); /* True by restriction (7) */
+ if( iFrom>0 && (pSubSrc->a[0].fg.jointype & JT_LTORJ)!=0 ){
+ return 0; /* Restriction (27a) */
+ }
+ if( pSubitem->fg.isCte && pSubitem->u2.pCteUse->eM10d==M10d_Yes ){
+ return 0; /* (28) */
+ }
+
+ /* Restriction (29):
+ **
+ ** We do not want two constraints on the same term of the flattened
+ ** query where one constraint has EP_InnerON and the other is EP_OuterON.
+ ** To prevent this, one or the other of the following conditions must be
+ ** false:
+ **
+ ** (29a) The right-most entry in the FROM clause of the subquery
+ ** must not be part of an outer join.
+ **
+ ** (29b) The subquery itself must not be the right operand of a
+ ** NATURAL join or a join that as an ON or USING clause.
+ **
+ ** These conditions are sufficient to keep an EP_OuterON from being
+ ** flattened into an EP_InnerON. Restrictions (3a) and (27a) prevent
+ ** an EP_InnerON from being flattened into an EP_OuterON.
+ */
+ if( pSubSrc->nSrc>=2
+ && (pSubSrc->a[pSubSrc->nSrc-1].fg.jointype & JT_OUTER)!=0
+ ){
+ if( (pSubitem->fg.jointype & JT_NATURAL)!=0
+ || pSubitem->fg.isUsing
+ || NEVER(pSubitem->u3.pOn!=0) /* ON clause already shifted into WHERE */
+ || pSubitem->fg.isOn
+ ){
+ return 0;
+ }
+ }
+
/* Restriction (17): If the sub-query is a compound SELECT, then it must
** use only the UNION ALL operator. And none of the simple select queries
** that make up the compound SELECT are allowed to be aggregate or distinct
@@ -138590,13 +145302,14 @@ static int flattenSubquery(
if( pSub->pOrderBy ){
return 0; /* Restriction (20) */
}
- if( isAgg || (p->selFlags & SF_Distinct)!=0 || pSrc->nSrc!=1 ){
- return 0; /* (17d1), (17d2), or (17d3) */
+ if( isAgg || (p->selFlags & SF_Distinct)!=0 || isOuterJoin>0 ){
+ return 0; /* (17d1), (17d2), or (17f) */
}
for(pSub1=pSub; pSub1; pSub1=pSub1->pPrior){
testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct );
testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Aggregate );
assert( pSub->pSrc!=0 );
+ assert( (pSub->selFlags & SF_Recursive)==0 );
assert( pSub->pEList->nExpr==pSub1->pEList->nExpr );
if( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))!=0 /* (17b) */
|| (pSub1->pPrior && pSub1->op!=TK_ALL) /* (17a) */
@@ -138607,6 +145320,12 @@ static int flattenSubquery(
){
return 0;
}
+ if( iFrom>0 && (pSub1->pSrc->a[0].fg.jointype & JT_LTORJ)!=0 ){
+ /* Without this restriction, the JT_LTORJ flag would end up being
+ ** omitted on left-hand tables of the right join that is being
+ ** flattened. */
+ return 0; /* Restrictions (17g), (27b) */
+ }
testcase( pSub1->pSrc->nSrc>1 );
}
@@ -138617,15 +145336,17 @@ static int flattenSubquery(
if( p->pOrderBy->a[ii].u.x.iOrderByCol==0 ) return 0;
}
}
- }
- /* Ex-restriction (23):
- ** The only way that the recursive part of a CTE can contain a compound
- ** subquery is for the subquery to be one term of a join. But if the
- ** subquery is a join, then the flattening has already been stopped by
- ** restriction (17d3)
- */
- assert( (p->selFlags & SF_Recursive)==0 || pSub->pPrior==0 );
+ /* Restriction (23) */
+ if( (p->selFlags & SF_Recursive) ) return 0;
+
+ if( pSrc->nSrc>1 ){
+ if( pParse->nSelect>500 ) return 0;
+ if( OptimizationDisabled(db, SQLITE_FlttnUnionAll) ) return 0;
+ aCsrMap = sqlcipher_sqlite3DbMallocZero(db, ((i64)pParse->nTab+1)*sizeof(int));
+ if( aCsrMap ) aCsrMap[0] = pParse->nTab;
+ }
+ }
/***** If we reach this point, flattening is permitted. *****/
SELECTTRACE(1,pParse,p,("flatten %u.%p from term %d\n",
@@ -138637,6 +145358,17 @@ static int flattenSubquery(
testcase( i==SQLITE_DENY );
pParse->zAuthContext = zSavedAuthContext;
+ /* Delete the transient structures associated with thesubquery */
+ pSub1 = pSubitem->pSelect;
+ sqlcipher_sqlite3DbFree(db, pSubitem->zDatabase);
+ sqlcipher_sqlite3DbFree(db, pSubitem->zName);
+ sqlcipher_sqlite3DbFree(db, pSubitem->zAlias);
+ pSubitem->zDatabase = 0;
+ pSubitem->zName = 0;
+ pSubitem->zAlias = 0;
+ pSubitem->pSelect = 0;
+ assert( pSubitem->fg.isUsing!=0 || pSubitem->u3.pOn==0 );
+
/* If the sub-query is a compound SELECT statement, then (by restrictions
** 17 and 18 above) it must be a UNION ALL and the parent query must
** be of the form:
@@ -138675,18 +145407,23 @@ static int flattenSubquery(
ExprList *pOrderBy = p->pOrderBy;
Expr *pLimit = p->pLimit;
Select *pPrior = p->pPrior;
+ Table *pItemTab = pSubitem->pTab;
+ pSubitem->pTab = 0;
p->pOrderBy = 0;
- p->pSrc = 0;
p->pPrior = 0;
p->pLimit = 0;
pNew = sqlcipher_sqlite3SelectDup(db, p, 0);
p->pLimit = pLimit;
p->pOrderBy = pOrderBy;
- p->pSrc = pSrc;
p->op = TK_ALL;
+ pSubitem->pTab = pItemTab;
if( pNew==0 ){
p->pPrior = pPrior;
}else{
+ pNew->selId = ++pParse->nSelect;
+ if( aCsrMap && ALWAYS(db->mallocFailed==0) ){
+ renumberCursors(pParse, pNew, iFrom, aCsrMap);
+ }
pNew->pPrior = pPrior;
if( pPrior ) pPrior->pNext = pNew;
pNew->pNext = p;
@@ -138694,24 +145431,13 @@ static int flattenSubquery(
SELECTTRACE(2,pParse,p,("compound-subquery flattener"
" creates %u as peer\n",pNew->selId));
}
- if( db->mallocFailed ) return 1;
+ assert( pSubitem->pSelect==0 );
+ }
+ sqlcipher_sqlite3DbFree(db, aCsrMap);
+ if( db->mallocFailed ){
+ pSubitem->pSelect = pSub1;
+ return 1;
}
-
- /* Begin flattening the iFrom-th entry of the FROM clause
- ** in the outer query.
- */
- pSub = pSub1 = pSubitem->pSelect;
-
- /* Delete the transient table structure associated with the
- ** subquery
- */
- sqlcipher_sqlite3DbFree(db, pSubitem->zDatabase);
- sqlcipher_sqlite3DbFree(db, pSubitem->zName);
- sqlcipher_sqlite3DbFree(db, pSubitem->zAlias);
- pSubitem->zDatabase = 0;
- pSubitem->zName = 0;
- pSubitem->zAlias = 0;
- pSubitem->pSelect = 0;
/* Defer deleting the Table object associated with the
** subquery until code generation is
@@ -138724,8 +145450,10 @@ static int flattenSubquery(
Table *pTabToDel = pSubitem->pTab;
if( pTabToDel->nTabRef==1 ){
Parse *pToplevel = sqlcipher_sqlite3ParseToplevel(pParse);
- pTabToDel->pNextZombie = pToplevel->pZombieTab;
- pToplevel->pZombieTab = pTabToDel;
+ sqlcipher_sqlite3ParserAddCleanup(pToplevel,
+ (void(*)(sqlcipher_sqlite3*,void*))sqlcipher_sqlite3DeleteTable,
+ pTabToDel);
+ testcase( pToplevel->earlyCleanup );
}else{
pTabToDel->nTabRef--;
}
@@ -138745,22 +145473,18 @@ static int flattenSubquery(
** those references with expressions that resolve to the subquery FROM
** elements we are now copying in.
*/
+ pSub = pSub1;
for(pParent=p; pParent; pParent=pParent->pPrior, pSub=pSub->pPrior){
int nSubSrc;
u8 jointype = 0;
+ u8 ltorj = pSrc->a[iFrom].fg.jointype & JT_LTORJ;
assert( pSub!=0 );
pSubSrc = pSub->pSrc; /* FROM clause of subquery */
nSubSrc = pSubSrc->nSrc; /* Number of terms in subquery FROM clause */
pSrc = pParent->pSrc; /* FROM clause of the outer query */
- if( pSrc ){
- assert( pParent==p ); /* First time through the loop */
- jointype = pSubitem->fg.jointype;
- }else{
- assert( pParent!=p ); /* 2nd and subsequent times through the loop */
- pSrc = sqlcipher_sqlite3SrcListAppend(pParse, 0, 0, 0);
- if( pSrc==0 ) break;
- pParent->pSrc = pSrc;
+ if( pParent==p ){
+ jointype = pSubitem->fg.jointype; /* First time through the loop */
}
/* The subquery uses a single slot of the FROM clause of the outer
@@ -138788,13 +145512,16 @@ static int flattenSubquery(
** outer query.
*/
for(i=0; i<nSubSrc; i++){
- sqlcipher_sqlite3IdListDelete(db, pSrc->a[i+iFrom].pUsing);
- assert( pSrc->a[i+iFrom].fg.isTabFunc==0 );
- pSrc->a[i+iFrom] = pSubSrc->a[i];
+ SrcItem *pItem = &pSrc->a[i+iFrom];
+ if( pItem->fg.isUsing ) sqlcipher_sqlite3IdListDelete(db, pItem->u3.pUsing);
+ assert( pItem->fg.isTabFunc==0 );
+ *pItem = pSubSrc->a[i];
+ pItem->fg.jointype |= ltorj;
iNewParent = pSubSrc->a[i].iCursor;
memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i]));
}
- pSrc->a[iFrom].fg.jointype = jointype;
+ pSrc->a[iFrom].fg.jointype &= JT_LTORJ;
+ pSrc->a[iFrom].fg.jointype |= jointype | ltorj;
/* Now begin substituting subquery result set expressions for
** references to the iParent in the outer query.
@@ -138829,8 +145556,8 @@ static int flattenSubquery(
}
pWhere = pSub->pWhere;
pSub->pWhere = 0;
- if( isLeftJoin>0 ){
- sqlcipher_sqlite3SetJoinExpr(pWhere, iNewParent);
+ if( isOuterJoin>0 ){
+ sqlcipher_sqlite3SetJoinExpr(pWhere, iNewParent, EP_OuterON);
}
if( pWhere ){
if( pParent->pWhere ){
@@ -138844,7 +145571,7 @@ static int flattenSubquery(
x.pParse = pParse;
x.iTable = iParent;
x.iNewTable = iNewParent;
- x.isLeftJoin = isLeftJoin;
+ x.isOuterJoin = isOuterJoin;
x.pEList = pSub->pEList;
substSelect(&x, pParent, 0);
}
@@ -138879,8 +145606,8 @@ static int flattenSubquery(
sqlcipher_sqlite3WalkSelect(&w,pSub1);
sqlcipher_sqlite3SelectDelete(db, pSub1);
-#if SELECTTRACE_ENABLED
- if( sqlcipher_sqlite3_unsupported_selecttrace & 0x100 ){
+#if TREETRACE_ENABLED
+ if( sqlcipher_sqlite3TreeTrace & 0x100 ){
SELECTTRACE(0x100,pParse,p,("After flattening:\n"));
sqlcipher_sqlite3TreeViewSelect(0, p, 0);
}
@@ -138897,8 +145624,12 @@ static int flattenSubquery(
typedef struct WhereConst WhereConst;
struct WhereConst {
Parse *pParse; /* Parsing context */
+ u8 *pOomFault; /* Pointer to pParse->db->mallocFailed */
int nConst; /* Number for COLUMN=CONSTANT terms */
int nChng; /* Number of times a constant is propagated */
+ int bHasAffBlob; /* At least one column in apExpr[] as affinity BLOB */
+ u32 mExcludeOn; /* Which ON expressions to exclude from considertion.
+ ** Either EP_OuterON or EP_InnerON|EP_OuterON */
Expr **apExpr; /* [i*2] is COLUMN and [i*2+1] is VALUE */
};
@@ -138937,6 +145668,9 @@ static void constInsert(
return; /* Already present. Return without doing anything. */
}
}
+ if( sqlcipher_sqlite3ExprAffinity(pColumn)==SQLITE_AFF_BLOB ){
+ pConst->bHasAffBlob = 1;
+ }
pConst->nConst++;
pConst->apExpr = sqlcipher_sqlite3DbReallocOrFree(pConst->pParse->db, pConst->apExpr,
@@ -138957,8 +145691,12 @@ static void constInsert(
*/
static void findConstInWhere(WhereConst *pConst, Expr *pExpr){
Expr *pRight, *pLeft;
- if( pExpr==0 ) return;
- if( ExprHasProperty(pExpr, EP_FromJoin) ) return;
+ if( NEVER(pExpr==0) ) return;
+ if( ExprHasProperty(pExpr, pConst->mExcludeOn) ){
+ testcase( ExprHasProperty(pExpr, EP_OuterON) );
+ testcase( ExprHasProperty(pExpr, EP_InnerON) );
+ return;
+ }
if( pExpr->op==TK_AND ){
findConstInWhere(pConst, pExpr->pRight);
findConstInWhere(pConst, pExpr->pLeft);
@@ -138978,38 +145716,85 @@ static void findConstInWhere(WhereConst *pConst, Expr *pExpr){
}
/*
-** This is a Walker expression callback. pExpr is a candidate expression
-** to be replaced by a value. If pExpr is equivalent to one of the
-** columns named in pWalker->u.pConst, then overwrite it with its
-** corresponding value.
+** This is a helper function for Walker callback propagateConstantExprRewrite().
+**
+** Argument pExpr is a candidate expression to be replaced by a value. If
+** pExpr is equivalent to one of the columns named in pWalker->u.pConst,
+** then overwrite it with the corresponding value. Except, do not do so
+** if argument bIgnoreAffBlob is non-zero and the affinity of pExpr
+** is SQLITE_AFF_BLOB.
*/
-static int propagateConstantExprRewrite(Walker *pWalker, Expr *pExpr){
+static int propagateConstantExprRewriteOne(
+ WhereConst *pConst,
+ Expr *pExpr,
+ int bIgnoreAffBlob
+){
int i;
- WhereConst *pConst;
+ if( pConst->pOomFault[0] ) return WRC_Prune;
if( pExpr->op!=TK_COLUMN ) return WRC_Continue;
- if( ExprHasProperty(pExpr, EP_FixedCol|EP_FromJoin) ){
+ if( ExprHasProperty(pExpr, EP_FixedCol|pConst->mExcludeOn) ){
testcase( ExprHasProperty(pExpr, EP_FixedCol) );
- testcase( ExprHasProperty(pExpr, EP_FromJoin) );
+ testcase( ExprHasProperty(pExpr, EP_OuterON) );
+ testcase( ExprHasProperty(pExpr, EP_InnerON) );
return WRC_Continue;
}
- pConst = pWalker->u.pConst;
for(i=0; i<pConst->nConst; i++){
Expr *pColumn = pConst->apExpr[i*2];
if( pColumn==pExpr ) continue;
if( pColumn->iTable!=pExpr->iTable ) continue;
if( pColumn->iColumn!=pExpr->iColumn ) continue;
+ if( bIgnoreAffBlob && sqlcipher_sqlite3ExprAffinity(pColumn)==SQLITE_AFF_BLOB ){
+ break;
+ }
/* A match is found. Add the EP_FixedCol property */
pConst->nChng++;
ExprClearProperty(pExpr, EP_Leaf);
ExprSetProperty(pExpr, EP_FixedCol);
assert( pExpr->pLeft==0 );
pExpr->pLeft = sqlcipher_sqlite3ExprDup(pConst->pParse->db, pConst->apExpr[i*2+1], 0);
+ if( pConst->pParse->db->mallocFailed ) return WRC_Prune;
break;
}
return WRC_Prune;
}
/*
+** This is a Walker expression callback. pExpr is a node from the WHERE
+** clause of a SELECT statement. This function examines pExpr to see if
+** any substitutions based on the contents of pWalker->u.pConst should
+** be made to pExpr or its immediate children.
+**
+** A substitution is made if:
+**
+** + pExpr is a column with an affinity other than BLOB that matches
+** one of the columns in pWalker->u.pConst, or
+**
+** + pExpr is a binary comparison operator (=, <=, >=, <, >) that
+** uses an affinity other than TEXT and one of its immediate
+** children is a column that matches one of the columns in
+** pWalker->u.pConst.
+*/
+static int propagateConstantExprRewrite(Walker *pWalker, Expr *pExpr){
+ WhereConst *pConst = pWalker->u.pConst;
+ assert( TK_GT==TK_EQ+1 );
+ assert( TK_LE==TK_EQ+2 );
+ assert( TK_LT==TK_EQ+3 );
+ assert( TK_GE==TK_EQ+4 );
+ if( pConst->bHasAffBlob ){
+ if( (pExpr->op>=TK_EQ && pExpr->op<=TK_GE)
+ || pExpr->op==TK_IS
+ ){
+ propagateConstantExprRewriteOne(pConst, pExpr->pLeft, 0);
+ if( pConst->pOomFault[0] ) return WRC_Prune;
+ if( sqlcipher_sqlite3ExprAffinity(pExpr->pLeft)!=SQLITE_AFF_TEXT ){
+ propagateConstantExprRewriteOne(pConst, pExpr->pRight, 0);
+ }
+ }
+ }
+ return propagateConstantExprRewriteOne(pConst, pExpr, pConst->bHasAffBlob);
+}
+
+/*
** The WHERE-clause constant propagation optimization.
**
** If the WHERE clause contains terms of the form COLUMN=CONSTANT or
@@ -139044,6 +145829,21 @@ static int propagateConstantExprRewrite(Walker *pWalker, Expr *pExpr){
** routines know to generate the constant "123" instead of looking up the
** column value. Also, to avoid collation problems, this optimization is
** only attempted if the "a=123" term uses the default BINARY collation.
+**
+** 2021-05-25 forum post 6a06202608: Another troublesome case is...
+**
+** CREATE TABLE t1(x);
+** INSERT INTO t1 VALUES(10.0);
+** SELECT 1 FROM t1 WHERE x=10 AND x LIKE 10;
+**
+** The query should return no rows, because the t1.x value is '10.0' not '10'
+** and '10.0' is not LIKE '10'. But if we are not careful, the first WHERE
+** term "x=10" will cause the second WHERE term to become "10 LIKE 10",
+** resulting in a false positive. To avoid this, constant propagation for
+** columns with BLOB affinity is only allowed if the constant is used with
+** operators ==, <=, <, >=, >, or IS in a way that will cause the correct
+** type conversions to occur. See logic associated with the bHasAffBlob flag
+** for details.
*/
static int propagateConstants(
Parse *pParse, /* The parsing context */
@@ -139053,10 +145853,23 @@ static int propagateConstants(
Walker w;
int nChng = 0;
x.pParse = pParse;
+ x.pOomFault = &pParse->db->mallocFailed;
do{
x.nConst = 0;
x.nChng = 0;
x.apExpr = 0;
+ x.bHasAffBlob = 0;
+ if( ALWAYS(p->pSrc!=0)
+ && p->pSrc->nSrc>0
+ && (p->pSrc->a[0].fg.jointype & JT_LTORJ)!=0
+ ){
+ /* Do not propagate constants on any ON clause if there is a
+ ** RIGHT JOIN anywhere in the query */
+ x.mExcludeOn = EP_InnerON | EP_OuterON;
+ }else{
+ /* Do not propagate constants through the ON clause of a LEFT JOIN */
+ x.mExcludeOn = EP_OuterON;
+ }
findConstInWhere(&x, p->pWhere);
if( x.nConst ){
memset(&w, 0, sizeof(w));
@@ -139075,6 +145888,35 @@ static int propagateConstants(
}
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
+# if !defined(SQLITE_OMIT_WINDOWFUNC)
+/*
+** This function is called to determine whether or not it is safe to
+** push WHERE clause expression pExpr down to FROM clause sub-query
+** pSubq, which contains at least one window function. Return 1
+** if it is safe and the expression should be pushed down, or 0
+** otherwise.
+**
+** It is only safe to push the expression down if it consists only
+** of constants and copies of expressions that appear in the PARTITION
+** BY clause of all window function used by the sub-query. It is safe
+** to filter out entire partitions, but not rows within partitions, as
+** this may change the results of the window functions.
+**
+** At the time this function is called it is guaranteed that
+**
+** * the sub-query uses only one distinct window frame, and
+** * that the window frame has a PARTITION BY clase.
+*/
+static int pushDownWindowCheck(Parse *pParse, Select *pSubq, Expr *pExpr){
+ assert( pSubq->pWin->pPartition );
+ assert( (pSubq->selFlags & SF_MultiPart)==0 );
+ assert( pSubq->pPrior==0 );
+ return sqlcipher_sqlite3ExprIsConstantOrGroupBy(pParse, pExpr, pSubq->pWin->pPartition);
+}
+# endif /* SQLITE_OMIT_WINDOWFUNC */
+#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
+
+#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
/*
** Make copies of relevant WHERE clause terms of the outer query into
** the WHERE clause of subquery. Example:
@@ -139121,9 +145963,24 @@ static int propagateConstants(
** But if the (b2=2) term were to be pushed down into the bb subquery,
** then the (1,1,NULL) row would be suppressed.
**
-** (6) The inner query features one or more window-functions (since
-** changes to the WHERE clause of the inner query could change the
-** window over which window functions are calculated).
+** (6) Window functions make things tricky as changes to the WHERE clause
+** of the inner query could change the window over which window
+** functions are calculated. Therefore, do not attempt the optimization
+** if:
+**
+** (6a) The inner query uses multiple incompatible window partitions.
+**
+** (6b) The inner query is a compound and uses window-functions.
+**
+** (6c) The WHERE clause does not consist entirely of constants and
+** copies of expressions found in the PARTITION BY clause of
+** all window-functions used by the sub-query. It is safe to
+** filter out entire partitions, as this does not change the
+** window over which any window-function is calculated.
+**
+** (7) The inner query is a Common Table Expression (CTE) that should
+** be materialized. (This restriction is implemented in the calling
+** routine.)
**
** Return 0 if no changes are made and non-zero if one or more WHERE clause
** terms are duplicated into the subquery.
@@ -139132,18 +145989,22 @@ static int pushDownWhereTerms(
Parse *pParse, /* Parse context (for malloc() and error reporting) */
Select *pSubq, /* The subquery whose WHERE clause is to be augmented */
Expr *pWhere, /* The WHERE clause of the outer query */
- int iCursor, /* Cursor number of the subquery */
- int isLeftJoin /* True if pSubq is the right term of a LEFT JOIN */
+ SrcItem *pSrc /* The subquery term of the outer FROM clause */
){
Expr *pNew;
int nChng = 0;
- Select *pSel;
if( pWhere==0 ) return 0;
- if( pSubq->selFlags & SF_Recursive ) return 0; /* restriction (2) */
+ if( pSubq->selFlags & (SF_Recursive|SF_MultiPart) ) return 0;
+ if( pSrc->fg.jointype & (JT_LTORJ|JT_RIGHT) ) return 0;
#ifndef SQLITE_OMIT_WINDOWFUNC
- for(pSel=pSubq; pSel; pSel=pSel->pPrior){
- if( pSel->pWin ) return 0; /* restriction (6) */
+ if( pSubq->pPrior ){
+ Select *pSel;
+ for(pSel=pSubq; pSel; pSel=pSel->pPrior){
+ if( pSel->pWin ) return 0; /* restriction (6b) */
+ }
+ }else{
+ if( pSubq->pWin && pSubq->pWin->pPartition==0 ) return 0;
}
#endif
@@ -139164,31 +146025,45 @@ static int pushDownWhereTerms(
return 0; /* restriction (3) */
}
while( pWhere->op==TK_AND ){
- nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight,
- iCursor, isLeftJoin);
+ nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight, pSrc);
pWhere = pWhere->pLeft;
}
+
+#if 0 /* Legacy code. Checks now done by sqlcipher_sqlite3ExprIsTableConstraint() */
if( isLeftJoin
- && (ExprHasProperty(pWhere,EP_FromJoin)==0
- || pWhere->iRightJoinTable!=iCursor)
+ && (ExprHasProperty(pWhere,EP_OuterON)==0
+ || pWhere->w.iJoin!=iCursor)
){
return 0; /* restriction (4) */
}
- if( ExprHasProperty(pWhere,EP_FromJoin) && pWhere->iRightJoinTable!=iCursor ){
+ if( ExprHasProperty(pWhere,EP_OuterON)
+ && pWhere->w.iJoin!=iCursor
+ ){
return 0; /* restriction (5) */
}
- if( sqlcipher_sqlite3ExprIsTableConstant(pWhere, iCursor) ){
+#endif
+
+ if( sqlcipher_sqlite3ExprIsTableConstraint(pWhere, pSrc) ){
nChng++;
+ pSubq->selFlags |= SF_PushDown;
while( pSubq ){
SubstContext x;
pNew = sqlcipher_sqlite3ExprDup(pParse->db, pWhere, 0);
- unsetJoinExpr(pNew, -1);
+ unsetJoinExpr(pNew, -1, 1);
x.pParse = pParse;
- x.iTable = iCursor;
- x.iNewTable = iCursor;
- x.isLeftJoin = 0;
+ x.iTable = pSrc->iCursor;
+ x.iNewTable = pSrc->iCursor;
+ x.isOuterJoin = 0;
x.pEList = pSubq->pEList;
pNew = substExpr(&x, pNew);
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ if( pSubq->pWin && 0==pushDownWindowCheck(pParse, pSubq, pNew) ){
+ /* Restriction 6c has prevented push-down in this case */
+ sqlcipher_sqlite3ExprDelete(pParse->db, pNew);
+ nChng--;
+ break;
+ }
+#endif
if( pSubq->selFlags & SF_Aggregate ){
pSubq->pHaving = sqlcipher_sqlite3ExprAnd(pParse, pSubq->pHaving, pNew);
}else{
@@ -139219,7 +146094,7 @@ static int pushDownWhereTerms(
*/
static u8 minMaxQuery(sqlcipher_sqlite3 *db, Expr *pFunc, ExprList **ppMinMax){
int eRet = WHERE_ORDERBY_NORMAL; /* Return value */
- ExprList *pEList = pFunc->x.pList; /* Arguments to agg function */
+ ExprList *pEList; /* Arguments to agg function */
const char *zFunc; /* Name of aggregate function pFunc */
ExprList *pOrderBy;
u8 sortFlags = 0;
@@ -139227,9 +146102,16 @@ static u8 minMaxQuery(sqlcipher_sqlite3 *db, Expr *pFunc, ExprList **ppMinMax){
assert( *ppMinMax==0 );
assert( pFunc->op==TK_AGG_FUNCTION );
assert( !IsWindowFunc(pFunc) );
- if( pEList==0 || pEList->nExpr!=1 || ExprHasProperty(pFunc, EP_WinFunc) ){
+ assert( ExprUseXList(pFunc) );
+ pEList = pFunc->x.pList;
+ if( pEList==0
+ || pEList->nExpr!=1
+ || ExprHasProperty(pFunc, EP_WinFunc)
+ || OptimizationDisabled(db, SQLITE_MinMaxOpt)
+ ){
return eRet;
}
+ assert( !ExprHasProperty(pFunc, EP_IntValue) );
zFunc = pFunc->u.zToken;
if( sqlcipher_sqlite3StrICmp(zFunc, "min")==0 ){
eRet = WHERE_ORDERBY_MIN;
@@ -139244,7 +146126,7 @@ static u8 minMaxQuery(sqlcipher_sqlite3 *db, Expr *pFunc, ExprList **ppMinMax){
}
*ppMinMax = pOrderBy = sqlcipher_sqlite3ExprListDup(db, pEList, 0);
assert( pOrderBy!=0 || db->mallocFailed );
- if( pOrderBy ) pOrderBy->a[0].sortFlags = sortFlags;
+ if( pOrderBy ) pOrderBy->a[0].fg.sortFlags = sortFlags;
return eRet;
}
@@ -139257,7 +146139,13 @@ static u8 minMaxQuery(sqlcipher_sqlite3 *db, Expr *pFunc, ExprList **ppMinMax){
**
** where table is a database table, not a sub-select or view. If the query
** does match this pattern, then a pointer to the Table object representing
-** <tbl> is returned. Otherwise, 0 is returned.
+** <tbl> is returned. Otherwise, NULL is returned.
+**
+** This routine checks to see if it is safe to use the count optimization.
+** A correct answer is still obtained (though perhaps more slowly) if
+** this routine returns NULL when it could have returned a table pointer.
+** But returning the pointer when NULL should have been returned can
+** result in incorrect answers and/or crashes. So, when in doubt, return NULL.
*/
static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){
Table *pTab;
@@ -139265,19 +146153,27 @@ static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){
assert( !p->pGroupBy );
- if( p->pWhere || p->pEList->nExpr!=1
- || p->pSrc->nSrc!=1 || p->pSrc->a[0].pSelect
+ if( p->pWhere
+ || p->pEList->nExpr!=1
+ || p->pSrc->nSrc!=1
+ || p->pSrc->a[0].pSelect
+ || pAggInfo->nFunc!=1
+ || p->pHaving
){
return 0;
}
pTab = p->pSrc->a[0].pTab;
+ assert( pTab!=0 );
+ assert( !IsView(pTab) );
+ if( !IsOrdinaryTable(pTab) ) return 0;
pExpr = p->pEList->a[0].pExpr;
- assert( pTab && !pTab->pSelect && pExpr );
-
- if( IsVirtual(pTab) ) return 0;
+ assert( pExpr!=0 );
if( pExpr->op!=TK_AGG_FUNCTION ) return 0;
- if( NEVER(pAggInfo->nFunc==0) ) return 0;
+ if( pExpr->pAggInfo!=pAggInfo ) return 0;
if( (pAggInfo->aFunc[0].pFunc->funcFlags&SQLITE_FUNC_COUNT)==0 ) return 0;
+ assert( pAggInfo->aFunc[0].pFExpr==pExpr );
+ testcase( ExprHasProperty(pExpr, EP_Distinct) );
+ testcase( ExprHasProperty(pExpr, EP_WinFunc) );
if( ExprHasProperty(pExpr, EP_Distinct|EP_WinFunc) ) return 0;
return pTab;
@@ -139290,24 +146186,27 @@ static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){
** SQLITE_ERROR and leave an error in pParse. Otherwise, populate
** pFrom->pIndex and return SQLITE_OK.
*/
-SQLITE_PRIVATE int sqlcipher_sqlite3IndexedByLookup(Parse *pParse, struct SrcList_item *pFrom){
- if( pFrom->pTab && pFrom->fg.isIndexedBy ){
- Table *pTab = pFrom->pTab;
- char *zIndexedBy = pFrom->u1.zIndexedBy;
- Index *pIdx;
- for(pIdx=pTab->pIndex;
- pIdx && sqlcipher_sqlite3StrICmp(pIdx->zName, zIndexedBy);
- pIdx=pIdx->pNext
- );
- if( !pIdx ){
- sqlcipher_sqlite3ErrorMsg(pParse, "no such index: %s", zIndexedBy, 0);
- pParse->checkSchema = 1;
- return SQLITE_ERROR;
- }
- pFrom->pIBIndex = pIdx;
+SQLITE_PRIVATE int sqlcipher_sqlite3IndexedByLookup(Parse *pParse, SrcItem *pFrom){
+ Table *pTab = pFrom->pTab;
+ char *zIndexedBy = pFrom->u1.zIndexedBy;
+ Index *pIdx;
+ assert( pTab!=0 );
+ assert( pFrom->fg.isIndexedBy!=0 );
+
+ for(pIdx=pTab->pIndex;
+ pIdx && sqlcipher_sqlite3StrICmp(pIdx->zName, zIndexedBy);
+ pIdx=pIdx->pNext
+ );
+ if( !pIdx ){
+ sqlcipher_sqlite3ErrorMsg(pParse, "no such index: %s", zIndexedBy, 0);
+ pParse->checkSchema = 1;
+ return SQLITE_ERROR;
}
+ assert( pFrom->fg.isCte==0 );
+ pFrom->u2.pIBIndex = pIdx;
return SQLITE_OK;
}
+
/*
** Detect compound SELECT statements that use an ORDER BY clause with
** an alternative collating sequence.
@@ -139364,7 +146263,7 @@ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){
pNew = sqlcipher_sqlite3DbMallocZero(db, sizeof(*pNew) );
if( pNew==0 ) return WRC_Abort;
memset(&dummy, 0, sizeof(dummy));
- pNewSrc = sqlcipher_sqlite3SrcListAppendFromTerm(pParse,0,0,0,&dummy,pNew,0,0);
+ pNewSrc = sqlcipher_sqlite3SrcListAppendFromTerm(pParse,0,0,0,&dummy,pNew,0);
if( pNewSrc==0 ) return WRC_Abort;
*pNew = *p;
p->pSrc = pNewSrc;
@@ -139394,7 +146293,7 @@ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){
** arguments. If it does, leave an error message in pParse and return
** non-zero, since pFrom is not allowed to be a table-valued function.
*/
-static int cannotBeFunction(Parse *pParse, struct SrcList_item *pFrom){
+static int cannotBeFunction(Parse *pParse, SrcItem *pFrom){
if( pFrom->fg.isTabFunc ){
sqlcipher_sqlite3ErrorMsg(pParse, "'%s' is not a function", pFrom->zName);
return 1;
@@ -139415,21 +146314,22 @@ static int cannotBeFunction(Parse *pParse, struct SrcList_item *pFrom){
*/
static struct Cte *searchWith(
With *pWith, /* Current innermost WITH clause */
- struct SrcList_item *pItem, /* FROM clause element to resolve */
+ SrcItem *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( sqlcipher_sqlite3StrICmp(zName, p->a[i].zName)==0 ){
- *ppContext = p;
- return &p->a[i];
- }
+ const char *zName = pItem->zName;
+ With *p;
+ assert( pItem->zDatabase==0 );
+ assert( zName!=0 );
+ for(p=pWith; p; p=p->pOuter){
+ int i;
+ for(i=0; i<p->nCte; i++){
+ if( sqlcipher_sqlite3StrICmp(zName, p->a[i].zName)==0 ){
+ *ppContext = p;
+ return &p->a[i];
}
}
+ if( p->bView ) break;
}
return 0;
}
@@ -139439,52 +146339,83 @@ static struct Cte *searchWith(
**
** 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
+** WITH clause will never be popped from the stack but should instead
+** 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.
+**
+** This routine returns a copy of pWith. Or, if bFree is true and
+** the pWith object is destroyed immediately due to an OOM condition,
+** then this routine return NULL.
+**
+** If bFree is true, do not continue to use the pWith pointer after
+** calling this routine, Instead, use only the return value.
*/
-SQLITE_PRIVATE void sqlcipher_sqlite3WithPush(Parse *pParse, With *pWith, u8 bFree){
- assert( bFree==0 || (pParse->pWith==0 && pParse->pWithToFree==0) );
+SQLITE_PRIVATE With *sqlcipher_sqlite3WithPush(Parse *pParse, With *pWith, u8 bFree){
if( pWith ){
- assert( pParse->pWith!=pWith );
- pWith->pOuter = pParse->pWith;
- pParse->pWith = pWith;
- if( bFree ) pParse->pWithToFree = pWith;
+ if( bFree ){
+ pWith = (With*)sqlcipher_sqlite3ParserAddCleanup(pParse,
+ (void(*)(sqlcipher_sqlite3*,void*))sqlcipher_sqlite3WithDelete,
+ pWith);
+ if( pWith==0 ) return 0;
+ }
+ if( pParse->nErr==0 ){
+ assert( pParse->pWith!=pWith );
+ pWith->pOuter = pParse->pWith;
+ pParse->pWith = pWith;
+ }
}
+ return pWith;
}
/*
** 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.
+** a WITH clause on the stack currently maintained by the parser (on the
+** pParse->pWith linked list). And if currently processing a CTE
+** CTE expression, through routine checks to see if the reference is
+** a recursive reference to the 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.
+** If pFrom matches a CTE according to either of these two above, pFrom->pTab
+** and other fields are populated accordingly.
**
-** 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.
+** Return 0 if no match is found.
+** Return 1 if a match is found.
+** Return 2 if an error condition is detected.
*/
-static int withExpand(
- Walker *pWalker,
- struct SrcList_item *pFrom
+static int resolveFromTermToCte(
+ Parse *pParse, /* The parsing context */
+ Walker *pWalker, /* Current tree walker */
+ SrcItem *pFrom /* The FROM clause term to check */
){
- Parse *pParse = pWalker->pParse;
- sqlcipher_sqlite3 *db = pParse->db;
- struct Cte *pCte; /* Matched CTE (or NULL if no match) */
- With *pWith; /* WITH clause that pCte belongs to */
+ Cte *pCte; /* Matched CTE (or NULL if no match) */
+ With *pWith; /* The matching WITH */
assert( pFrom->pTab==0 );
+ if( pParse->pWith==0 ){
+ /* There are no WITH clauses in the stack. No match is possible */
+ return 0;
+ }
if( pParse->nErr ){
- return SQLITE_ERROR;
+ /* Prior errors might have left pParse->pWith in a goofy state, so
+ ** go no further. */
+ return 0;
+ }
+ if( pFrom->zDatabase!=0 ){
+ /* The FROM term contains a schema qualifier (ex: main.t1) and so
+ ** it cannot possibly be a CTE reference. */
+ return 0;
+ }
+ if( pFrom->fg.notCte ){
+ /* The FROM term is specifically excluded from matching a CTE.
+ ** (1) It is part of a trigger that used to have zDatabase but had
+ ** zDatabase removed by sqlcipher_sqlite3FixTriggerStep().
+ ** (2) This is the first term in the FROM clause of an UPDATE.
+ */
+ return 0;
}
-
pCte = searchWith(pParse->pWith, pFrom, &pWith);
if( pCte ){
+ sqlcipher_sqlite3 *db = pParse->db;
Table *pTab;
ExprList *pEList;
Select *pSel;
@@ -139493,6 +146424,7 @@ static int withExpand(
int bMayRecursive; /* True if compound joined by UNION [ALL] */
With *pSavedWith; /* Initial value of pParse->pWith */
int iRecTab = -1; /* Cursor for recursive table */
+ CteUse *pCteUse;
/* If pCte->zCteErr is non-NULL at this point, then this is an illegal
** recursive reference to CTE pCte. Leave an error in pParse and return
@@ -139500,21 +146432,44 @@ static int withExpand(
** In this case, proceed. */
if( pCte->zCteErr ){
sqlcipher_sqlite3ErrorMsg(pParse, pCte->zCteErr, pCte->zName);
- return SQLITE_ERROR;
+ return 2;
}
- if( cannotBeFunction(pParse, pFrom) ) return SQLITE_ERROR;
+ if( cannotBeFunction(pParse, pFrom) ) return 2;
assert( pFrom->pTab==0 );
- pFrom->pTab = pTab = sqlcipher_sqlite3DbMallocZero(db, sizeof(Table));
- if( pTab==0 ) return WRC_Abort;
+ pTab = sqlcipher_sqlite3DbMallocZero(db, sizeof(Table));
+ if( pTab==0 ) return 2;
+ pCteUse = pCte->pUse;
+ if( pCteUse==0 ){
+ pCte->pUse = pCteUse = sqlcipher_sqlite3DbMallocZero(db, sizeof(pCteUse[0]));
+ if( pCteUse==0
+ || sqlcipher_sqlite3ParserAddCleanup(pParse,sqlcipher_sqlite3DbFree,pCteUse)==0
+ ){
+ sqlcipher_sqlite3DbFree(db, pTab);
+ return 2;
+ }
+ pCteUse->eM10d = pCte->eM10d;
+ }
+ pFrom->pTab = pTab;
pTab->nTabRef = 1;
pTab->zName = sqlcipher_sqlite3DbStrDup(db, pCte->zName);
pTab->iPKey = -1;
pTab->nRowLogEst = 200; assert( 200==sqlcipher_sqlite3LogEst(1048576) );
pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid;
pFrom->pSelect = sqlcipher_sqlite3SelectDup(db, pCte->pSelect, 0);
- if( db->mallocFailed ) return SQLITE_NOMEM_BKPT;
+ if( db->mallocFailed ) return 2;
+ pFrom->pSelect->selFlags |= SF_CopyCte;
assert( pFrom->pSelect );
+ if( pFrom->fg.isIndexedBy ){
+ sqlcipher_sqlite3ErrorMsg(pParse, "no such index: \"%s\"", pFrom->u1.zIndexedBy);
+ return 2;
+ }
+ pFrom->fg.isCte = 1;
+ pFrom->u2.pCteUse = pCteUse;
+ pCteUse->nUse++;
+ if( pCteUse->nUse>=2 && pCteUse->eM10d==M10d_Any ){
+ pCteUse->eM10d = M10d_Yes;
+ }
/* Check if this is a recursive CTE. */
pRecTerm = pSel = pFrom->pSelect;
@@ -139524,7 +146479,7 @@ static int withExpand(
SrcList *pSrc = pRecTerm->pSrc;
assert( pRecTerm->pPrior!=0 );
for(i=0; i<pSrc->nSrc; i++){
- struct SrcList_item *pItem = &pSrc->a[i];
+ SrcItem *pItem = &pSrc->a[i];
if( pItem->zDatabase==0
&& pItem->zName!=0
&& 0==sqlcipher_sqlite3StrICmp(pItem->zName, pCte->zName)
@@ -139536,7 +146491,7 @@ static int withExpand(
sqlcipher_sqlite3ErrorMsg(pParse,
"multiple references to recursive table: %s", pCte->zName
);
- return SQLITE_ERROR;
+ return 2;
}
pRecTerm->selFlags |= SF_Recursive;
if( iRecTab<0 ) iRecTab = pParse->nTab++;
@@ -139551,16 +146506,24 @@ static int withExpand(
pSavedWith = pParse->pWith;
pParse->pWith = pWith;
if( pSel->selFlags & SF_Recursive ){
+ int rc;
assert( pRecTerm!=0 );
assert( (pRecTerm->selFlags & SF_Recursive)==0 );
assert( pRecTerm->pNext!=0 );
assert( (pRecTerm->pNext->selFlags & SF_Recursive)!=0 );
assert( pRecTerm->pWith==0 );
pRecTerm->pWith = pSel->pWith;
- sqlcipher_sqlite3WalkSelect(pWalker, pRecTerm);
+ rc = sqlcipher_sqlite3WalkSelect(pWalker, pRecTerm);
pRecTerm->pWith = 0;
+ if( rc ){
+ pParse->pWith = pSavedWith;
+ return 2;
+ }
}else{
- sqlcipher_sqlite3WalkSelect(pWalker, pSel);
+ if( sqlcipher_sqlite3WalkSelect(pWalker, pSel) ){
+ pParse->pWith = pSavedWith;
+ return 2;
+ }
}
pParse->pWith = pWith;
@@ -139572,7 +146535,7 @@ static int withExpand(
pCte->zName, pEList->nExpr, pCte->pCols->nExpr
);
pParse->pWith = pSavedWith;
- return SQLITE_ERROR;
+ return 2;
}
pEList = pCte->pCols;
}
@@ -139588,9 +146551,9 @@ static int withExpand(
}
pCte->zCteErr = 0;
pParse->pWith = pSavedWith;
+ return 1; /* Success */
}
-
- return SQLITE_OK;
+ return 0; /* No match */
}
#endif
@@ -139603,7 +146566,7 @@ static int withExpand(
** sqlcipher_sqlite3SelectExpand() when walking a SELECT tree to resolve table
** names and other FROM clause elements.
*/
-static void selectPopWith(Walker *pWalker, Select *p){
+SQLITE_PRIVATE void sqlcipher_sqlite3SelectPopWith(Walker *pWalker, Select *p){
Parse *pParse = pWalker->pParse;
if( OK_IF_ALWAYS_TRUE(pParse->pWith) && p->pPrior==0 ){
With *pWith = findRightmost(p)->pWith;
@@ -139613,8 +146576,6 @@ static void selectPopWith(Walker *pWalker, Select *p){
}
}
}
-#else
-#define selectPopWith 0
#endif
/*
@@ -139624,7 +146585,7 @@ static void selectPopWith(Walker *pWalker, Select *p){
** SQLITE_OK is returned. Otherwise, if an OOM error is encountered,
** SQLITE_NOMEM.
*/
-SQLITE_PRIVATE int sqlcipher_sqlite3ExpandSubquery(Parse *pParse, struct SrcList_item *pFrom){
+SQLITE_PRIVATE int sqlcipher_sqlite3ExpandSubquery(Parse *pParse, SrcItem *pFrom){
Select *pSel = pFrom->pSelect;
Table *pTab;
@@ -139635,17 +146596,47 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ExpandSubquery(Parse *pParse, struct SrcList
if( pFrom->zAlias ){
pTab->zName = sqlcipher_sqlite3DbStrDup(pParse->db, pFrom->zAlias);
}else{
- pTab->zName = sqlcipher_sqlite3MPrintf(pParse->db, "subquery_%u", pSel->selId);
+ pTab->zName = sqlcipher_sqlite3MPrintf(pParse->db, "%!S", pFrom);
}
while( pSel->pPrior ){ pSel = pSel->pPrior; }
sqlcipher_sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol);
pTab->iPKey = -1;
pTab->nRowLogEst = 200; assert( 200==sqlcipher_sqlite3LogEst(1048576) );
- pTab->tabFlags |= TF_Ephemeral;
-
+#ifndef SQLITE_ALLOW_ROWID_IN_VIEW
+ /* The usual case - do not allow ROWID on a subquery */
+ pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid;
+#else
+ pTab->tabFlags |= TF_Ephemeral; /* Legacy compatibility mode */
+#endif
return pParse->nErr ? SQLITE_ERROR : SQLITE_OK;
}
+
+/*
+** Check the N SrcItem objects to the right of pBase. (N might be zero!)
+** If any of those SrcItem objects have a USING clause containing zName
+** then return true.
+**
+** If N is zero, or none of the N SrcItem objects to the right of pBase
+** contains a USING clause, or if none of the USING clauses contain zName,
+** then return false.
+*/
+static int inAnyUsingClause(
+ const char *zName, /* Name we are looking for */
+ SrcItem *pBase, /* The base SrcItem. Looking at pBase[1] and following */
+ int N /* How many SrcItems to check */
+){
+ while( N>0 ){
+ N--;
+ pBase++;
+ if( pBase->fg.isUsing==0 ) continue;
+ if( NEVER(pBase->u3.pUsing==0) ) continue;
+ if( sqlcipher_sqlite3IdListIndex(pBase->u3.pUsing, zName)>=0 ) return 1;
+ }
+ return 0;
+}
+
+
/*
** This routine is a Walker callback for "expanding" a SELECT statement.
** "Expanding" means to do the following:
@@ -139672,10 +146663,10 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ExpandSubquery(Parse *pParse, struct SrcList
*/
static int selectExpander(Walker *pWalker, Select *p){
Parse *pParse = pWalker->pParse;
- int i, j, k;
+ int i, j, k, rc;
SrcList *pTabList;
ExprList *pEList;
- struct SrcList_item *pFrom;
+ SrcItem *pFrom;
sqlcipher_sqlite3 *db = pParse->db;
Expr *pE, *pRight, *pExpr;
u16 selFlags = p->selFlags;
@@ -139695,6 +146686,15 @@ static int selectExpander(Walker *pWalker, Select *p){
}
pTabList = p->pSrc;
pEList = p->pEList;
+ if( pParse->pWith && (p->selFlags & SF_View) ){
+ if( p->pWith==0 ){
+ p->pWith = (With*)sqlcipher_sqlite3DbMallocZero(db, sizeof(With));
+ if( p->pWith==0 ){
+ return WRC_Abort;
+ }
+ }
+ p->pWith->bView = 1;
+ }
sqlcipher_sqlite3WithPush(pParse, p->pWith, 0);
/* Make sure cursor numbers have been assigned to all entries in
@@ -139711,10 +146711,6 @@ static int selectExpander(Walker *pWalker, Select *p){
assert( pFrom->fg.isRecursive==0 || pFrom->pTab!=0 );
if( pFrom->pTab ) continue;
assert( pFrom->fg.isRecursive==0 );
-#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;
@@ -139724,6 +146720,12 @@ static int selectExpander(Walker *pWalker, Select *p){
if( sqlcipher_sqlite3WalkSelect(pWalker, pSel) ) return WRC_Abort;
if( sqlcipher_sqlite3ExpandSubquery(pParse, pFrom) ) return WRC_Abort;
#endif
+#ifndef SQLITE_OMIT_CTE
+ }else if( (rc = resolveFromTermToCte(pParse, pWalker, pFrom))!=0 ){
+ if( rc>1 ) return WRC_Abort;
+ pTab = pFrom->pTab;
+ assert( pTab!=0 );
+#endif
}else{
/* An ordinary table or view name in the FROM clause */
assert( pFrom->pTab==0 );
@@ -139740,26 +146742,31 @@ static int selectExpander(Walker *pWalker, Select *p){
return WRC_Abort;
}
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
- if( IsVirtual(pTab) || pTab->pSelect ){
+ if( !IsOrdinaryTable(pTab) ){
i16 nCol;
u8 eCodeOrig = pWalker->eCode;
if( sqlcipher_sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort;
assert( pFrom->pSelect==0 );
- if( pTab->pSelect && (db->flags & SQLITE_EnableView)==0 ){
- sqlcipher_sqlite3ErrorMsg(pParse, "access to view \"%s\" prohibited",
- pTab->zName);
+ if( IsView(pTab) ){
+ if( (db->flags & SQLITE_EnableView)==0
+ && pTab->pSchema!=db->aDb[1].pSchema
+ ){
+ sqlcipher_sqlite3ErrorMsg(pParse, "access to view \"%s\" prohibited",
+ pTab->zName);
+ }
+ pFrom->pSelect = sqlcipher_sqlite3SelectDup(db, pTab->u.view.pSelect, 0);
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( IsVirtual(pTab)
+ else if( ALWAYS(IsVirtual(pTab))
&& pFrom->fg.fromDDL
- && ALWAYS(pTab->pVTable!=0)
- && pTab->pVTable->eVtabRisk > ((db->flags & SQLITE_TrustedSchema)!=0)
+ && ALWAYS(pTab->u.vtab.p!=0)
+ && pTab->u.vtab.p->eVtabRisk > ((db->flags & SQLITE_TrustedSchema)!=0)
){
sqlcipher_sqlite3ErrorMsg(pParse, "unsafe use of virtual table \"%s\"",
pTab->zName);
}
+ assert( SQLITE_VTABRISK_Normal==1 && SQLITE_VTABRISK_High==2 );
#endif
- pFrom->pSelect = sqlcipher_sqlite3SelectDup(db, pTab->pSelect, 0);
nCol = pTab->nCol;
pTab->nCol = -1;
pWalker->eCode = 1; /* Turn on Select.selId renumbering */
@@ -139771,14 +146778,15 @@ static int selectExpander(Walker *pWalker, Select *p){
}
/* Locate the index named by the INDEXED BY clause, if any. */
- if( sqlcipher_sqlite3IndexedByLookup(pParse, pFrom) ){
+ if( pFrom->fg.isIndexedBy && sqlcipher_sqlite3IndexedByLookup(pParse, pFrom) ){
return WRC_Abort;
}
}
/* Process NATURAL keywords, and ON and USING clauses of joins.
*/
- if( pParse->nErr || db->mallocFailed || sqliteProcessJoin(pParse, p) ){
+ assert( db->mallocFailed==0 || pParse->nErr!=0 );
+ if( pParse->nErr || sqlcipher_sqlite3ProcessJoin(pParse, p) ){
return WRC_Abort;
}
@@ -139826,7 +146834,7 @@ static int selectExpander(Walker *pWalker, Select *p){
pNew = sqlcipher_sqlite3ExprListAppend(pParse, pNew, a[k].pExpr);
if( pNew ){
pNew->a[pNew->nExpr-1].zEName = a[k].zEName;
- pNew->a[pNew->nExpr-1].eEName = a[k].eEName;
+ pNew->a[pNew->nExpr-1].fg.eEName = a[k].fg.eEName;
a[k].zEName = 0;
}
a[k].pExpr = 0;
@@ -139841,32 +146849,60 @@ static int selectExpander(Walker *pWalker, Select *p){
zTName = pE->pLeft->u.zToken;
}
for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
- Table *pTab = pFrom->pTab;
- Select *pSub = pFrom->pSelect;
- char *zTabName = pFrom->zAlias;
- const char *zSchemaName = 0;
- int iDb;
- if( zTabName==0 ){
+ Table *pTab = pFrom->pTab; /* Table for this data source */
+ ExprList *pNestedFrom; /* Result-set of a nested FROM clause */
+ char *zTabName; /* AS name for this data source */
+ const char *zSchemaName = 0; /* Schema name for this data source */
+ int iDb; /* Schema index for this data src */
+ IdList *pUsing; /* USING clause for pFrom[1] */
+
+ if( (zTabName = pFrom->zAlias)==0 ){
zTabName = pTab->zName;
}
if( db->mallocFailed ) break;
- if( pSub==0 || (pSub->selFlags & SF_NestedFrom)==0 ){
- pSub = 0;
+ assert( (int)pFrom->fg.isNestedFrom == IsNestedFrom(pFrom->pSelect) );
+ if( pFrom->fg.isNestedFrom ){
+ assert( pFrom->pSelect!=0 );
+ pNestedFrom = pFrom->pSelect->pEList;
+ assert( pNestedFrom!=0 );
+ assert( pNestedFrom->nExpr==pTab->nCol );
+ }else{
if( zTName && sqlcipher_sqlite3StrICmp(zTName, zTabName)!=0 ){
continue;
}
+ pNestedFrom = 0;
iDb = sqlcipher_sqlite3SchemaToIndex(db, pTab->pSchema);
zSchemaName = iDb>=0 ? db->aDb[iDb].zDbSName : "*";
}
+ if( i+1<pTabList->nSrc
+ && pFrom[1].fg.isUsing
+ && (selFlags & SF_NestedFrom)!=0
+ ){
+ int ii;
+ pUsing = pFrom[1].u3.pUsing;
+ for(ii=0; ii<pUsing->nId; ii++){
+ const char *zUName = pUsing->a[ii].zName;
+ pRight = sqlcipher_sqlite3Expr(db, TK_ID, zUName);
+ pNew = sqlcipher_sqlite3ExprListAppend(pParse, pNew, pRight);
+ if( pNew ){
+ struct ExprList_item *pX = &pNew->a[pNew->nExpr-1];
+ assert( pX->zEName==0 );
+ pX->zEName = sqlcipher_sqlite3MPrintf(db,"..%s", zUName);
+ pX->fg.eEName = ENAME_TAB;
+ pX->fg.bUsingTerm = 1;
+ }
+ }
+ }else{
+ pUsing = 0;
+ }
for(j=0; j<pTab->nCol; j++){
- char *zName = pTab->aCol[j].zName;
- char *zColname; /* The computed column name */
- char *zToFree; /* Malloced string that needs to be freed */
- Token sColname; /* Computed column name as a token */
+ char *zName = pTab->aCol[j].zCnName;
+ struct ExprList_item *pX; /* Newly added ExprList term */
assert( zName );
- if( zTName && pSub
- && sqlcipher_sqlite3MatchEName(&pSub->pEList->a[j], 0, zTName, 0)==0
+ if( zTName
+ && pNestedFrom
+ && sqlcipher_sqlite3MatchEName(&pNestedFrom->a[j], 0, zTName, 0)==0
){
continue;
}
@@ -139880,57 +146916,75 @@ static int selectExpander(Walker *pWalker, Select *p){
){
continue;
}
+ if( (pTab->aCol[j].colFlags & COLFLAG_NOEXPAND)!=0
+ && zTName==0
+ && (selFlags & (SF_NestedFrom))==0
+ ){
+ continue;
+ }
tableSeen = 1;
- if( i>0 && zTName==0 ){
- if( (pFrom->fg.jointype & JT_NATURAL)!=0
- && tableAndColumnIndex(pTabList, i, zName, 0, 0, 1)
+ if( i>0 && zTName==0 && (selFlags & SF_NestedFrom)==0 ){
+ if( pFrom->fg.isUsing
+ && sqlcipher_sqlite3IdListIndex(pFrom->u3.pUsing, zName)>=0
){
- /* In a NATURAL join, omit the join columns from the
- ** table to the right of the join */
- continue;
- }
- if( sqlcipher_sqlite3IdListIndex(pFrom->pUsing, zName)>=0 ){
/* In a join with a USING clause, omit columns in the
** using clause from the table on the right. */
continue;
}
}
pRight = sqlcipher_sqlite3Expr(db, TK_ID, zName);
- zColname = zName;
- zToFree = 0;
- if( longNames || pTabList->nSrc>1 ){
+ if( (pTabList->nSrc>1
+ && ( (pFrom->fg.jointype & JT_LTORJ)==0
+ || (selFlags & SF_NestedFrom)!=0
+ || !inAnyUsingClause(zName,pFrom,pTabList->nSrc-i-1)
+ )
+ )
+ || IN_RENAME_OBJECT
+ ){
Expr *pLeft;
pLeft = sqlcipher_sqlite3Expr(db, TK_ID, zTabName);
pExpr = sqlcipher_sqlite3PExpr(pParse, TK_DOT, pLeft, pRight);
+ if( IN_RENAME_OBJECT && pE->pLeft ){
+ sqlcipher_sqlite3RenameTokenRemap(pParse, pLeft, pE->pLeft);
+ }
if( zSchemaName ){
pLeft = sqlcipher_sqlite3Expr(db, TK_ID, zSchemaName);
pExpr = sqlcipher_sqlite3PExpr(pParse, TK_DOT, pLeft, pExpr);
}
- if( longNames ){
- zColname = sqlcipher_sqlite3MPrintf(db, "%s.%s", zTabName, zName);
- zToFree = zColname;
- }
}else{
pExpr = pRight;
}
pNew = sqlcipher_sqlite3ExprListAppend(pParse, pNew, pExpr);
- sqlcipher_sqlite3TokenInit(&sColname, zColname);
- sqlcipher_sqlite3ExprListSetName(pParse, pNew, &sColname, 0);
- if( pNew && (p->selFlags & SF_NestedFrom)!=0 && !IN_RENAME_OBJECT ){
- struct ExprList_item *pX = &pNew->a[pNew->nExpr-1];
- sqlcipher_sqlite3DbFree(db, pX->zEName);
- if( pSub ){
- pX->zEName = sqlcipher_sqlite3DbStrDup(db, pSub->pEList->a[j].zEName);
+ if( pNew==0 ){
+ break; /* OOM */
+ }
+ pX = &pNew->a[pNew->nExpr-1];
+ assert( pX->zEName==0 );
+ if( (selFlags & SF_NestedFrom)!=0 && !IN_RENAME_OBJECT ){
+ if( pNestedFrom ){
+ pX->zEName = sqlcipher_sqlite3DbStrDup(db, pNestedFrom->a[j].zEName);
testcase( pX->zEName==0 );
}else{
pX->zEName = sqlcipher_sqlite3MPrintf(db, "%s.%s.%s",
- zSchemaName, zTabName, zColname);
+ zSchemaName, zTabName, zName);
testcase( pX->zEName==0 );
}
- pX->eEName = ENAME_TAB;
+ pX->fg.eEName = ENAME_TAB;
+ if( (pFrom->fg.isUsing
+ && sqlcipher_sqlite3IdListIndex(pFrom->u3.pUsing, zName)>=0)
+ || (pUsing && sqlcipher_sqlite3IdListIndex(pUsing, zName)>=0)
+ || (pTab->aCol[j].colFlags & COLFLAG_NOEXPAND)!=0
+ ){
+ pX->fg.bNoExpand = 1;
+ }
+ }else if( longNames ){
+ pX->zEName = sqlcipher_sqlite3MPrintf(db, "%s.%s", zTabName, zName);
+ pX->fg.eEName = ENAME_NAME;
+ }else{
+ pX->zEName = sqlcipher_sqlite3DbStrDup(db, zName);
+ pX->fg.eEName = ENAME_NAME;
}
- sqlcipher_sqlite3DbFree(db, zToFree);
}
}
if( !tableSeen ){
@@ -139954,6 +147008,12 @@ static int selectExpander(Walker *pWalker, Select *p){
p->selFlags |= SF_ComplexResult;
}
}
+#if TREETRACE_ENABLED
+ if( sqlcipher_sqlite3TreeTrace & 0x100 ){
+ SELECTTRACE(0x100,pParse,p,("After result-set wildcard expansion:\n"));
+ sqlcipher_sqlite3TreeViewSelect(0, p, 0);
+ }
+#endif
return WRC_Continue;
}
@@ -139990,7 +147050,7 @@ static void sqlcipher_sqlite3SelectExpand(Parse *pParse, Select *pSelect){
sqlcipher_sqlite3WalkSelect(&w, pSelect);
}
w.xSelectCallback = selectExpander;
- w.xSelectCallback2 = selectPopWith;
+ w.xSelectCallback2 = sqlcipher_sqlite3SelectPopWith;
w.eCode = 0;
sqlcipher_sqlite3WalkSelect(&w, pSelect);
}
@@ -140014,7 +147074,7 @@ static void selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){
Parse *pParse;
int i;
SrcList *pTabList;
- struct SrcList_item *pFrom;
+ SrcItem *pFrom;
assert( p->selFlags & SF_Resolved );
if( p->selFlags & SF_HasTypeInfo ) return;
@@ -140075,12 +147135,13 @@ SQLITE_PRIVATE void sqlcipher_sqlite3SelectPrep(
NameContext *pOuterNC /* Name context for container */
){
assert( p!=0 || pParse->db->mallocFailed );
+ assert( pParse->db->pParse==pParse );
if( pParse->db->mallocFailed ) return;
if( p->selFlags & SF_HasTypeInfo ) return;
sqlcipher_sqlite3SelectExpand(pParse, p);
- if( pParse->nErr || pParse->db->mallocFailed ) return;
+ if( pParse->nErr ) return;
sqlcipher_sqlite3ResolveSelectNames(pParse, p, pOuterNC);
- if( pParse->nErr || pParse->db->mallocFailed ) return;
+ if( pParse->nErr ) return;
sqlcipher_sqlite3SelectAddTypeInfo(pParse, p);
}
@@ -140097,8 +147158,10 @@ static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){
int i;
struct AggInfo_func *pFunc;
int nReg = pAggInfo->nFunc + pAggInfo->nColumn;
+ assert( pParse->db->pParse==pParse );
+ assert( pParse->db->mallocFailed==0 || pParse->nErr!=0 );
if( nReg==0 ) return;
- if( pParse->nErr || pParse->db->mallocFailed ) return;
+ if( pParse->nErr ) return;
#ifdef SQLITE_DEBUG
/* Verify that all AggInfo registers are within the range specified by
** AggInfo.mnReg..AggInfo.mxReg */
@@ -140116,15 +147179,17 @@ static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){
for(pFunc=pAggInfo->aFunc, i=0; i<pAggInfo->nFunc; i++, pFunc++){
if( pFunc->iDistinct>=0 ){
Expr *pE = pFunc->pFExpr;
- assert( !ExprHasProperty(pE, EP_xIsSelect) );
+ assert( ExprUseXList(pE) );
if( pE->x.pList==0 || pE->x.pList->nExpr!=1 ){
sqlcipher_sqlite3ErrorMsg(pParse, "DISTINCT aggregates must have exactly one "
"argument");
pFunc->iDistinct = -1;
}else{
KeyInfo *pKeyInfo = sqlcipher_sqlite3KeyInfoFromExprList(pParse, pE->x.pList,0,0);
- sqlcipher_sqlite3VdbeAddOp4(v, OP_OpenEphemeral, pFunc->iDistinct, 0, 0,
- (char*)pKeyInfo, P4_KEYINFO);
+ pFunc->iDistAddr = sqlcipher_sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
+ pFunc->iDistinct, 0, 0, (char*)pKeyInfo, P4_KEYINFO);
+ ExplainQueryPlan((pParse, 0, "USE TEMP B-TREE FOR %s(DISTINCT)",
+ pFunc->pFunc->zName));
}
}
}
@@ -140139,8 +147204,9 @@ static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){
int i;
struct AggInfo_func *pF;
for(i=0, pF=pAggInfo->aFunc; i<pAggInfo->nFunc; i++, pF++){
- ExprList *pList = pF->pFExpr->x.pList;
- assert( !ExprHasProperty(pF->pFExpr, EP_xIsSelect) );
+ ExprList *pList;
+ assert( ExprUseXList(pF->pFExpr) );
+ pList = pF->pFExpr->x.pList;
sqlcipher_sqlite3VdbeAddOp2(v, OP_AggFinal, pF->iMem, pList ? pList->nExpr : 0);
sqlcipher_sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF);
}
@@ -140156,7 +147222,12 @@ static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){
** registers if register regAcc contains 0. The caller will take care
** of setting and clearing regAcc.
*/
-static void updateAccumulator(Parse *pParse, int regAcc, AggInfo *pAggInfo){
+static void updateAccumulator(
+ Parse *pParse,
+ int regAcc,
+ AggInfo *pAggInfo,
+ int eDistinctType
+){
Vdbe *v = pParse->pVdbe;
int i;
int regHit = 0;
@@ -140169,9 +147240,10 @@ static void updateAccumulator(Parse *pParse, int regAcc, AggInfo *pAggInfo){
int nArg;
int addrNext = 0;
int regAgg;
- ExprList *pList = pF->pFExpr->x.pList;
- assert( !ExprHasProperty(pF->pFExpr, EP_xIsSelect) );
+ ExprList *pList;
+ assert( ExprUseXList(pF->pFExpr) );
assert( !IsWindowFunc(pF->pFExpr) );
+ pList = pF->pFExpr->x.pList;
if( ExprHasProperty(pF->pFExpr, EP_WinFunc) ){
Expr *pFilter = pF->pFExpr->y.pWin->pFilter;
if( pAggInfo->nAccumulator
@@ -140202,13 +147274,12 @@ static void updateAccumulator(Parse *pParse, int regAcc, AggInfo *pAggInfo){
nArg = 0;
regAgg = 0;
}
- if( pF->iDistinct>=0 ){
+ if( pF->iDistinct>=0 && pList ){
if( addrNext==0 ){
addrNext = sqlcipher_sqlite3VdbeMakeLabel(pParse);
}
- testcase( nArg==0 ); /* Error condition */
- testcase( nArg>1 ); /* Also an error */
- codeDistinct(pParse, pF->iDistinct, addrNext, 1, regAgg);
+ pF->iDistinct = codeDistinct(pParse, eDistinctType,
+ pF->iDistinct, addrNext, pList, regAgg);
}
if( pF->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){
CollSeq *pColl = 0;
@@ -140260,7 +147331,7 @@ static void explainSimpleCount(
){
if( pParse->explain==2 ){
int bCover = (pIdx!=0 && (HasRowid(pTab) || !IsPrimaryKeyIndex(pIdx)));
- sqlcipher_sqlite3VdbeExplain(pParse, 0, "SCAN TABLE %s%s%s",
+ sqlcipher_sqlite3VdbeExplain(pParse, 0, "SCAN %s%s%s",
pTab->zName,
bCover ? " USING COVERING INDEX " : "",
bCover ? pIdx->zName : ""
@@ -140285,8 +147356,16 @@ static void explainSimpleCount(
static int havingToWhereExprCb(Walker *pWalker, Expr *pExpr){
if( pExpr->op!=TK_AND ){
Select *pS = pWalker->u.pSelect;
+ /* This routine is called before the HAVING clause of the current
+ ** SELECT is analyzed for aggregates. So if pExpr->pAggInfo is set
+ ** here, it indicates that the expression is a correlated reference to a
+ ** column from an outer aggregate query, or an aggregate function that
+ ** belongs to an outer query. Do not move the expression to the WHERE
+ ** clause in this obscure case, as doing so may corrupt the outer Select
+ ** statements AggInfo structure. */
if( sqlcipher_sqlite3ExprIsConstantOrGroupBy(pWalker->pParse, pExpr, pS->pGroupBy)
&& ExprAlwaysFalse(pExpr)==0
+ && pExpr->pAggInfo==0
){
sqlcipher_sqlite3 *db = pWalker->pParse->db;
Expr *pNew = sqlcipher_sqlite3Expr(db, TK_INTEGER, "1");
@@ -140325,8 +147404,8 @@ static void havingToWhere(Parse *pParse, Select *p){
sWalker.xExprCallback = havingToWhereExprCb;
sWalker.u.pSelect = p;
sqlcipher_sqlite3WalkExpr(&sWalker, p->pHaving);
-#if SELECTTRACE_ENABLED
- if( sWalker.eCode && (sqlcipher_sqlite3_unsupported_selecttrace & 0x100)!=0 ){
+#if TREETRACE_ENABLED
+ if( sWalker.eCode && (sqlcipher_sqlite3TreeTrace & 0x100)!=0 ){
SELECTTRACE(0x100,pParse,p,("Move HAVING terms into WHERE:\n"));
sqlcipher_sqlite3TreeViewSelect(0, p, 0);
}
@@ -140338,11 +147417,13 @@ static void havingToWhere(Parse *pParse, Select *p){
** If it is, then return the SrcList_item for the prior view. If it is not,
** then return 0.
*/
-static struct SrcList_item *isSelfJoinView(
+static SrcItem *isSelfJoinView(
SrcList *pTabList, /* Search for self-joins in this FROM clause */
- struct SrcList_item *pThis /* Search for prior reference to this subquery */
+ SrcItem *pThis /* Search for prior reference to this subquery */
){
- struct SrcList_item *pItem;
+ SrcItem *pItem;
+ assert( pThis->pSelect!=0 );
+ if( pThis->pSelect->selFlags & SF_PushDown ) return 0;
for(pItem = pTabList->a; pItem<pThis; pItem++){
Select *pS1;
if( pItem->pSelect==0 ) continue;
@@ -140358,9 +147439,7 @@ static struct SrcList_item *isSelfJoinView(
** names in the same FROM clause. */
continue;
}
- if( sqlcipher_sqlite3ExprCompare(0, pThis->pSelect->pWhere, pS1->pWhere, -1)
- || sqlcipher_sqlite3ExprCompare(0, pThis->pSelect->pHaving, pS1->pHaving, -1)
- ){
+ if( pItem->pSelect->selFlags & SF_PushDown ){
/* The view was modified by some other optimization such as
** pushDownWhereTerms() */
continue;
@@ -140370,6 +147449,15 @@ static struct SrcList_item *isSelfJoinView(
return 0;
}
+/*
+** Deallocate a single AggInfo object
+*/
+static void agginfoFree(sqlcipher_sqlite3 *db, AggInfo *p){
+ sqlcipher_sqlite3DbFree(db, p->aCol);
+ sqlcipher_sqlite3DbFree(db, p->aFunc);
+ sqlcipher_sqlite3DbFreeNN(db, p);
+}
+
#ifdef SQLITE_COUNTOFVIEW_OPTIMIZATION
/*
** Attempt to transform a query of the form
@@ -140401,7 +147489,9 @@ static int countOfViewOptimization(Parse *pParse, Select *p){
if( p->pGroupBy ) return 0;
pExpr = p->pEList->a[0].pExpr;
if( pExpr->op!=TK_AGG_FUNCTION ) return 0; /* Result is an aggregate */
+ assert( ExprUseUToken(pExpr) );
if( sqlcipher_sqlite3_stricmp(pExpr->u.zToken,"count") ) return 0; /* Is count() */
+ assert( ExprUseXList(pExpr) );
if( pExpr->x.pList!=0 ) return 0; /* Must be count(*) */
if( p->pSrc->nSrc!=1 ) return 0; /* One table in FROM */
pSub = p->pSrc->a[0].pSelect;
@@ -140447,8 +147537,8 @@ static int countOfViewOptimization(Parse *pParse, Select *p){
p->pEList->a[0].pExpr = pExpr;
p->selFlags &= ~SF_Aggregate;
-#if SELECTTRACE_ENABLED
- if( sqlcipher_sqlite3_unsupported_selecttrace & 0x400 ){
+#if TREETRACE_ENABLED
+ if( sqlcipher_sqlite3TreeTrace & 0x400 ){
SELECTTRACE(0x400,pParse,p,("After count-of-view optimization:\n"));
sqlcipher_sqlite3TreeViewSelect(0, p, 0);
}
@@ -140458,6 +147548,29 @@ static int countOfViewOptimization(Parse *pParse, Select *p){
#endif /* SQLITE_COUNTOFVIEW_OPTIMIZATION */
/*
+** If any term of pSrc, or any SF_NestedFrom sub-query, is not the same
+** as pSrcItem but has the same alias as p0, then return true.
+** Otherwise return false.
+*/
+static int sameSrcAlias(SrcItem *p0, SrcList *pSrc){
+ int i;
+ for(i=0; i<pSrc->nSrc; i++){
+ SrcItem *p1 = &pSrc->a[i];
+ if( p1==p0 ) continue;
+ if( p0->pTab==p1->pTab && 0==sqlcipher_sqlite3_stricmp(p0->zAlias, p1->zAlias) ){
+ return 1;
+ }
+ if( p1->pSelect
+ && (p1->pSelect->selFlags & SF_NestedFrom)!=0
+ && sameSrcAlias(p0, p1->pSelect->pSrc)
+ ){
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/*
** Generate code for the SELECT statement given in the p argument.
**
** The results are returned according to the SelectDest structure.
@@ -140494,15 +147607,21 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Select(
u8 minMaxFlag; /* Flag for min/max queries */
db = pParse->db;
+ assert( pParse==db->pParse );
v = sqlcipher_sqlite3GetVdbe(pParse);
- if( p==0 || db->mallocFailed || pParse->nErr ){
+ if( p==0 || pParse->nErr ){
return 1;
}
+ assert( db->mallocFailed==0 );
if( sqlcipher_sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1;
-#if SELECTTRACE_ENABLED
+#if TREETRACE_ENABLED
SELECTTRACE(1,pParse,p, ("begin processing:\n", pParse->addrExplain));
- if( sqlcipher_sqlite3_unsupported_selecttrace & 0x100 ){
- sqlcipher_sqlite3TreeViewSelect(0, p, 0);
+ if( sqlcipher_sqlite3TreeTrace & 0x10100 ){
+ if( (sqlcipher_sqlite3TreeTrace & 0x10001)==0x10000 ){
+ sqlcipher_sqlite3TreeViewLine(0, "In sqlcipher_sqlite3Select() at %s:%d",
+ __FILE__, __LINE__);
+ }
+ sqlcipher_sqlite3ShowSelect(p);
}
#endif
@@ -140515,53 +147634,72 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Select(
pDest->eDest==SRT_Except || pDest->eDest==SRT_Discard ||
pDest->eDest==SRT_DistQueue || pDest->eDest==SRT_DistFifo );
/* All of these destinations are also able to ignore the ORDER BY clause */
- sqlcipher_sqlite3ExprListDelete(db, p->pOrderBy);
- p->pOrderBy = 0;
+ if( p->pOrderBy ){
+#if TREETRACE_ENABLED
+ SELECTTRACE(1,pParse,p, ("dropping superfluous ORDER BY:\n"));
+ if( sqlcipher_sqlite3TreeTrace & 0x100 ){
+ sqlcipher_sqlite3TreeViewExprList(0, p->pOrderBy, 0, "ORDERBY");
+ }
+#endif
+ sqlcipher_sqlite3ParserAddCleanup(pParse,
+ (void(*)(sqlcipher_sqlite3*,void*))sqlcipher_sqlite3ExprListDelete,
+ p->pOrderBy);
+ testcase( pParse->earlyCleanup );
+ p->pOrderBy = 0;
+ }
p->selFlags &= ~SF_Distinct;
p->selFlags |= SF_NoopOrderBy;
}
sqlcipher_sqlite3SelectPrep(pParse, p, 0);
- if( pParse->nErr || db->mallocFailed ){
+ if( pParse->nErr ){
goto select_end;
}
+ assert( db->mallocFailed==0 );
assert( p->pEList!=0 );
-#if SELECTTRACE_ENABLED
- if( sqlcipher_sqlite3_unsupported_selecttrace & 0x104 ){
+#if TREETRACE_ENABLED
+ if( sqlcipher_sqlite3TreeTrace & 0x104 ){
SELECTTRACE(0x104,pParse,p, ("after name resolution:\n"));
sqlcipher_sqlite3TreeViewSelect(0, p, 0);
}
#endif
- /* If the SF_UpdateFrom flag is set, then this function is being called
+ /* If the SF_UFSrcCheck flag is set, then this function is being called
** as part of populating the temp table for an UPDATE...FROM statement.
** In this case, it is an error if the target object (pSrc->a[0]) name
- ** or alias is duplicated within FROM clause (pSrc->a[1..n]). */
- if( p->selFlags & SF_UpdateFrom ){
- struct SrcList_item *p0 = &p->pSrc->a[0];
- for(i=1; i<p->pSrc->nSrc; i++){
- struct SrcList_item *p1 = &p->pSrc->a[i];
- if( p0->pTab==p1->pTab && 0==sqlcipher_sqlite3_stricmp(p0->zAlias, p1->zAlias) ){
- sqlcipher_sqlite3ErrorMsg(pParse,
- "target object/alias may not appear in FROM clause: %s",
- p0->zAlias ? p0->zAlias : p0->pTab->zName
- );
- goto select_end;
- }
+ ** or alias is duplicated within FROM clause (pSrc->a[1..n]).
+ **
+ ** Postgres disallows this case too. The reason is that some other
+ ** systems handle this case differently, and not all the same way,
+ ** which is just confusing. To avoid this, we follow PG's lead and
+ ** disallow it altogether. */
+ if( p->selFlags & SF_UFSrcCheck ){
+ SrcItem *p0 = &p->pSrc->a[0];
+ if( sameSrcAlias(p0, p->pSrc) ){
+ sqlcipher_sqlite3ErrorMsg(pParse,
+ "target object/alias may not appear in FROM clause: %s",
+ p0->zAlias ? p0->zAlias : p0->pTab->zName
+ );
+ goto select_end;
}
+
+ /* Clear the SF_UFSrcCheck flag. The check has already been performed,
+ ** and leaving this flag set can cause errors if a compound sub-query
+ ** in p->pSrc is flattened into this query and this function called
+ ** again as part of compound SELECT processing. */
+ p->selFlags &= ~SF_UFSrcCheck;
}
if( pDest->eDest==SRT_Output ){
- generateColumnNames(pParse, p);
+ sqlcipher_sqlite3GenerateColumnNames(pParse, p);
}
#ifndef SQLITE_OMIT_WINDOWFUNC
- rc = sqlcipher_sqlite3WindowRewrite(pParse, p);
- if( rc ){
- assert( db->mallocFailed || pParse->nErr>0 );
+ if( sqlcipher_sqlite3WindowRewrite(pParse, p) ){
+ assert( pParse->nErr );
goto select_end;
}
-#if SELECTTRACE_ENABLED
- if( p->pWin && (sqlcipher_sqlite3_unsupported_selecttrace & 0x108)!=0 ){
+#if TREETRACE_ENABLED
+ if( p->pWin && (sqlcipher_sqlite3TreeTrace & 0x108)!=0 ){
SELECTTRACE(0x104,pParse,p, ("after window rewrite:\n"));
sqlcipher_sqlite3TreeViewSelect(0, p, 0);
}
@@ -140577,7 +147715,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Select(
*/
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
for(i=0; !p->pPrior && i<pTabList->nSrc; i++){
- struct SrcList_item *pItem = &pTabList->a[i];
+ SrcItem *pItem = &pTabList->a[i];
Select *pSub = pItem->pSelect;
Table *pTab = pItem->pTab;
@@ -140589,14 +147727,16 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Select(
/* Convert LEFT JOIN into JOIN if there are terms of the right table
** of the LEFT JOIN used in the WHERE clause.
*/
- if( (pItem->fg.jointype & JT_LEFT)!=0
+ if( (pItem->fg.jointype & (JT_LEFT|JT_RIGHT))==JT_LEFT
&& sqlcipher_sqlite3ExprImpliesNonNullRow(p->pWhere, pItem->iCursor)
&& OptimizationEnabled(db, SQLITE_SimplifyJoin)
){
SELECTTRACE(0x100,pParse,p,
("LEFT-JOIN simplifies to JOIN on term %d\n",i));
pItem->fg.jointype &= ~(JT_LEFT|JT_OUTER);
- unsetJoinExpr(p->pWhere, pItem->iCursor);
+ assert( pItem->iCursor>=0 );
+ unsetJoinExpr(p->pWhere, pItem->iCursor,
+ pTabList->a[0].fg.jointype & JT_LTORJ);
}
/* No futher action if this term of the FROM clause is no a subquery */
@@ -140620,6 +147760,41 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Select(
if( (pSub->selFlags & SF_Aggregate)!=0 ) continue;
assert( pSub->pGroupBy==0 );
+ /* If a FROM-clause subquery has an ORDER BY clause that is not
+ ** really doing anything, then delete it now so that it does not
+ ** interfere with query flattening. See the discussion at
+ ** https://sqlite.org/forum/forumpost/2d76f2bcf65d256a
+ **
+ ** Beware of these cases where the ORDER BY clause may not be safely
+ ** omitted:
+ **
+ ** (1) There is also a LIMIT clause
+ ** (2) The subquery was added to help with window-function
+ ** processing
+ ** (3) The subquery is in the FROM clause of an UPDATE
+ ** (4) The outer query uses an aggregate function other than
+ ** the built-in count(), min(), or max().
+ ** (5) The ORDER BY isn't going to accomplish anything because
+ ** one of:
+ ** (a) The outer query has a different ORDER BY clause
+ ** (b) The subquery is part of a join
+ ** See forum post 062d576715d277c8
+ */
+ if( pSub->pOrderBy!=0
+ && (p->pOrderBy!=0 || pTabList->nSrc>1) /* Condition (5) */
+ && pSub->pLimit==0 /* Condition (1) */
+ && (pSub->selFlags & SF_OrderByReqd)==0 /* Condition (2) */
+ && (p->selFlags & SF_OrderByReqd)==0 /* Condition (3) and (4) */
+ && OptimizationEnabled(db, SQLITE_OmitOrderBy)
+ ){
+ SELECTTRACE(0x100,pParse,p,
+ ("omit superfluous ORDER BY on %r FROM-clause subquery\n",i+1));
+ sqlcipher_sqlite3ParserAddCleanup(pParse,
+ (void(*)(sqlcipher_sqlite3*,void*))sqlcipher_sqlite3ExprListDelete,
+ pSub->pOrderBy);
+ pSub->pOrderBy = 0;
+ }
+
/* If the outer query contains a "complex" result set (that is,
** if the result set of the outer query uses functions or subqueries)
** and if the subquery contains an ORDER BY clause and if
@@ -140642,7 +147817,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Select(
&& i==0
&& (p->selFlags & SF_ComplexResult)!=0
&& (pTabList->nSrc==1
- || (pTabList->a[1].fg.jointype&(JT_LEFT|JT_CROSS))!=0)
+ || (pTabList->a[1].fg.jointype&(JT_OUTER|JT_CROSS))!=0)
){
continue;
}
@@ -140666,9 +147841,9 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Select(
*/
if( p->pPrior ){
rc = multiSelect(pParse, p, pDest);
-#if SELECTTRACE_ENABLED
+#if TREETRACE_ENABLED
SELECTTRACE(0x1,pParse,p,("end compound-select processing\n"));
- if( (sqlcipher_sqlite3_unsupported_selecttrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){
+ if( (sqlcipher_sqlite3TreeTrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){
sqlcipher_sqlite3TreeViewSelect(0, p, 0);
}
#endif
@@ -140682,12 +147857,13 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Select(
** as the equivalent optimization will be handled by query planner in
** sqlcipher_sqlite3WhereBegin().
*/
- if( pTabList->nSrc>1
+ if( p->pWhere!=0
+ && p->pWhere->op==TK_AND
&& OptimizationEnabled(db, SQLITE_PropagateConst)
&& propagateConstants(pParse, p)
){
-#if SELECTTRACE_ENABLED
- if( sqlcipher_sqlite3_unsupported_selecttrace & 0x100 ){
+#if TREETRACE_ENABLED
+ if( sqlcipher_sqlite3TreeTrace & 0x100 ){
SELECTTRACE(0x100,pParse,p,("After constant propagation:\n"));
sqlcipher_sqlite3TreeViewSelect(0, p, 0);
}
@@ -140711,7 +147887,8 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Select(
** (2) Generate code for all sub-queries
*/
for(i=0; i<pTabList->nSrc; i++){
- struct SrcList_item *pItem = &pTabList->a[i];
+ SrcItem *pItem = &pTabList->a[i];
+ SrcItem *pPrior;
SelectDest dest;
Select *pSub;
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
@@ -140744,19 +147921,8 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Select(
pSub = pItem->pSelect;
if( pSub==0 ) continue;
- /* The code for a subquery should only be generated once, though it is
- ** technically harmless for it to be generated multiple times. The
- ** following assert() will detect if something changes to cause
- ** the same subquery to be coded multiple times, as a signal to the
- ** developers to try to optimize the situation.
- **
- ** Update 2019-07-24:
- ** See ticket https://sqlite.org/src/tktview/c52b09c7f38903b1311cec40.
- ** The dbsqlfuzz fuzzer found a case where the same subquery gets
- ** coded twice. So this assert() now becomes a testcase(). It should
- ** be very rare, though.
- */
- testcase( pItem->addrFillSub!=0 );
+ /* The code for a subquery should only be generated once. */
+ assert( pItem->addrFillSub==0 );
/* Increment Parse.nHeight by the height of the largest expression
** tree referred to by this, the parent select. The child select
@@ -140771,16 +147937,18 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Select(
** inside the subquery. This can help the subquery to run more efficiently.
*/
if( OptimizationEnabled(db, SQLITE_PushDown)
- && pushDownWhereTerms(pParse, pSub, p->pWhere, pItem->iCursor,
- (pItem->fg.jointype & JT_OUTER)!=0)
+ && (pItem->fg.isCte==0
+ || (pItem->u2.pCteUse->eM10d!=M10d_Yes && pItem->u2.pCteUse->nUse<2))
+ && pushDownWhereTerms(pParse, pSub, p->pWhere, pItem)
){
-#if SELECTTRACE_ENABLED
- if( sqlcipher_sqlite3_unsupported_selecttrace & 0x100 ){
+#if TREETRACE_ENABLED
+ if( sqlcipher_sqlite3TreeTrace & 0x100 ){
SELECTTRACE(0x100,pParse,p,
("After WHERE-clause push-down into subquery %d:\n", pSub->selId));
sqlcipher_sqlite3TreeViewSelect(0, p, 0);
}
#endif
+ assert( pItem->pSelect && (pItem->pSelect->selFlags & SF_PushDown)!=0 );
}else{
SELECTTRACE(0x100,pParse,p,("Push-down not possible\n"));
}
@@ -140790,16 +147958,19 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Select(
/* Generate code to implement the subquery
**
- ** The subquery is implemented as a co-routine if the subquery is
- ** guaranteed to be the outer loop (so that it does not need to be
- ** computed more than once)
+ ** The subquery is implemented as a co-routine if all of the following are
+ ** true:
**
- ** TODO: Are there other reasons beside (1) to use a co-routine
- ** implementation?
+ ** (1) the subquery is guaranteed to be the outer loop (so that
+ ** it does not need to be computed more than once), and
+ ** (2) the subquery is not a CTE that should be materialized
+ ** (3) the subquery is not part of a left operand for a RIGHT JOIN
*/
if( i==0
&& (pTabList->nSrc==1
- || (pTabList->a[1].fg.jointype&(JT_LEFT|JT_CROSS))!=0) /* (1) */
+ || (pTabList->a[1].fg.jointype&(JT_OUTER|JT_CROSS))!=0) /* (1) */
+ && (pItem->fg.isCte==0 || pItem->u2.pCteUse->eM10d!=M10d_Yes) /* (2) */
+ && (pTabList->a[0].fg.jointype & JT_LTORJ)==0 /* (3) */
){
/* Implement a co-routine that will return a single row of the result
** set on each invocation.
@@ -140808,10 +147979,10 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Select(
pItem->regReturn = ++pParse->nMem;
sqlcipher_sqlite3VdbeAddOp3(v, OP_InitCoroutine, pItem->regReturn, 0, addrTop);
- VdbeComment((v, "%s", pItem->pTab->zName));
+ VdbeComment((v, "%!S", pItem));
pItem->addrFillSub = addrTop;
sqlcipher_sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn);
- ExplainQueryPlan((pParse, 1, "CO-ROUTINE %u", pSub->selId));
+ ExplainQueryPlan((pParse, 1, "CO-ROUTINE %!S", pItem));
sqlcipher_sqlite3Select(pParse, pSub, &dest);
pItem->pTab->nRowLogEst = pSub->nSelectRow;
pItem->fg.viaCoroutine = 1;
@@ -140819,46 +147990,62 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Select(
sqlcipher_sqlite3VdbeEndCoroutine(v, pItem->regReturn);
sqlcipher_sqlite3VdbeJumpHere(v, addrTop-1);
sqlcipher_sqlite3ClearTempRegCache(pParse);
- }else{
- /* Generate a subroutine that will fill an ephemeral table with
- ** the content of this subquery. pItem->addrFillSub will point
- ** to the address of the generated subroutine. pItem->regReturn
- ** is a register allocated to hold the subroutine return address
- */
+ }else if( pItem->fg.isCte && pItem->u2.pCteUse->addrM9e>0 ){
+ /* This is a CTE for which materialization code has already been
+ ** generated. Invoke the subroutine to compute the materialization,
+ ** the make the pItem->iCursor be a copy of the ephemerial table that
+ ** holds the result of the materialization. */
+ CteUse *pCteUse = pItem->u2.pCteUse;
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_Gosub, pCteUse->regRtn, pCteUse->addrM9e);
+ if( pItem->iCursor!=pCteUse->iCur ){
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_OpenDup, pItem->iCursor, pCteUse->iCur);
+ VdbeComment((v, "%!S", pItem));
+ }
+ pSub->nSelectRow = pCteUse->nRowEst;
+ }else if( (pPrior = isSelfJoinView(pTabList, pItem))!=0 ){
+ /* This view has already been materialized by a prior entry in
+ ** this same FROM clause. Reuse it. */
+ if( pPrior->addrFillSub ){
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_Gosub, pPrior->regReturn, pPrior->addrFillSub);
+ }
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_OpenDup, pItem->iCursor, pPrior->iCursor);
+ pSub->nSelectRow = pPrior->pSelect->nSelectRow;
+ }else{
+ /* Materialize the view. If the view is not correlated, generate a
+ ** subroutine to do the materialization so that subsequent uses of
+ ** the same view can reuse the materialization. */
int topAddr;
int onceAddr = 0;
- int retAddr;
- struct SrcList_item *pPrior;
- testcase( pItem->addrFillSub==0 ); /* Ticket c52b09c7f38903b1311 */
pItem->regReturn = ++pParse->nMem;
- topAddr = sqlcipher_sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn);
+ topAddr = sqlcipher_sqlite3VdbeAddOp0(v, OP_Goto);
pItem->addrFillSub = topAddr+1;
+ pItem->fg.isMaterialized = 1;
if( pItem->fg.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 = sqlcipher_sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
- VdbeComment((v, "materialize \"%s\"", pItem->pTab->zName));
- }else{
- VdbeNoopComment((v, "materialize \"%s\"", pItem->pTab->zName));
- }
- pPrior = isSelfJoinView(pTabList, pItem);
- if( pPrior ){
- sqlcipher_sqlite3VdbeAddOp2(v, OP_OpenDup, pItem->iCursor, pPrior->iCursor);
- assert( pPrior->pSelect!=0 );
- pSub->nSelectRow = pPrior->pSelect->nSelectRow;
+ VdbeComment((v, "materialize %!S", pItem));
}else{
- sqlcipher_sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
- ExplainQueryPlan((pParse, 1, "MATERIALIZE %u", pSub->selId));
- sqlcipher_sqlite3Select(pParse, pSub, &dest);
+ VdbeNoopComment((v, "materialize %!S", pItem));
}
+ sqlcipher_sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
+ ExplainQueryPlan((pParse, 1, "MATERIALIZE %!S", pItem));
+ sqlcipher_sqlite3Select(pParse, pSub, &dest);
pItem->pTab->nRowLogEst = pSub->nSelectRow;
if( onceAddr ) sqlcipher_sqlite3VdbeJumpHere(v, onceAddr);
- retAddr = sqlcipher_sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn);
- VdbeComment((v, "end %s", pItem->pTab->zName));
- sqlcipher_sqlite3VdbeChangeP1(v, topAddr, retAddr);
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_Return, pItem->regReturn, topAddr+1);
+ VdbeComment((v, "end %!S", pItem));
+ sqlcipher_sqlite3VdbeJumpHere(v, topAddr);
sqlcipher_sqlite3ClearTempRegCache(pParse);
+ if( pItem->fg.isCte && pItem->fg.isCorrelated==0 ){
+ CteUse *pCteUse = pItem->u2.pCteUse;
+ pCteUse->addrM9e = pItem->addrFillSub;
+ pCteUse->regRtn = pItem->regReturn;
+ pCteUse->iCur = pItem->iCursor;
+ pCteUse->nRowEst = pSub->nSelectRow;
+ }
}
if( db->mallocFailed ) goto select_end;
pParse->nHeight -= sqlcipher_sqlite3SelectExprHeight(p);
@@ -140874,8 +148061,8 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Select(
pHaving = p->pHaving;
sDistinct.isTnct = (p->selFlags & SF_Distinct)!=0;
-#if SELECTTRACE_ENABLED
- if( sqlcipher_sqlite3_unsupported_selecttrace & 0x400 ){
+#if TREETRACE_ENABLED
+ if( sqlcipher_sqlite3TreeTrace & 0x400 ){
SELECTTRACE(0x400,pParse,p,("After all FROM-clause analysis:\n"));
sqlcipher_sqlite3TreeViewSelect(0, p, 0);
}
@@ -140909,9 +148096,10 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Select(
** the sDistinct.isTnct is still set. Hence, isTnct represents the
** original setting of the SF_Distinct flag, not the current setting */
assert( sDistinct.isTnct );
+ sDistinct.isTnct = 2;
-#if SELECTTRACE_ENABLED
- if( sqlcipher_sqlite3_unsupported_selecttrace & 0x400 ){
+#if TREETRACE_ENABLED
+ if( sqlcipher_sqlite3TreeTrace & 0x400 ){
SELECTTRACE(0x400,pParse,p,("Transform DISTINCT into GROUP BY:\n"));
sqlcipher_sqlite3TreeViewSelect(0, p, 0);
}
@@ -140944,6 +148132,18 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Select(
*/
if( pDest->eDest==SRT_EphemTab ){
sqlcipher_sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pDest->iSDParm, pEList->nExpr);
+ if( p->selFlags & SF_NestedFrom ){
+ /* Delete or NULL-out result columns that will never be used */
+ int ii;
+ for(ii=pEList->nExpr-1; ii>0 && pEList->a[ii].fg.bUsed==0; ii--){
+ sqlcipher_sqlite3ExprDelete(db, pEList->a[ii].pExpr);
+ sqlcipher_sqlite3DbFree(db, pEList->a[ii].zEName);
+ pEList->nExpr--;
+ }
+ for(ii=0; ii<pEList->nExpr; ii++){
+ if( pEList->a[ii].fg.bUsed==0 ) pEList->a[ii].pExpr->op = TK_NULL;
+ }
+ }
}
/* Set the limiter.
@@ -140988,7 +148188,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Select(
/* Begin the database scan. */
SELECTTRACE(1,pParse,p,("WhereBegin\n"));
pWInfo = sqlcipher_sqlite3WhereBegin(pParse, pTabList, pWhere, sSort.pOrderBy,
- p->pEList, wctrlFlags, p->nSelectRow);
+ p->pEList, p, wctrlFlags, p->nSelectRow);
if( pWInfo==0 ) goto select_end;
if( sqlcipher_sqlite3WhereOutputRowCount(pWInfo) < p->nSelectRow ){
p->nSelectRow = sqlcipher_sqlite3WhereOutputRowCount(pWInfo);
@@ -141003,6 +148203,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Select(
sSort.pOrderBy = 0;
}
}
+ SELECTTRACE(1,pParse,p,("WhereBegin returns\n"));
/* If sorting index that was created by a prior OP_OpenEphemeral
** instruction ended up not being needed, then change the OP_OpenEphemeral
@@ -141041,6 +148242,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Select(
/* End the database scan loop.
*/
+ SELECTTRACE(1,pParse,p,("WhereEnd\n"));
sqlcipher_sqlite3WhereEnd(pWInfo);
}
}else{
@@ -141091,8 +148293,9 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Select(
** ORDER BY to maximize the chances of rows being delivered in an
** order that makes the ORDER BY redundant. */
for(ii=0; ii<pGroupBy->nExpr; ii++){
- u8 sortFlags = sSort.pOrderBy->a[ii].sortFlags & KEYINFO_ORDER_DESC;
- pGroupBy->a[ii].sortFlags = sortFlags;
+ u8 sortFlags;
+ sortFlags = sSort.pOrderBy->a[ii].fg.sortFlags & KEYINFO_ORDER_DESC;
+ pGroupBy->a[ii].fg.sortFlags = sortFlags;
}
if( sqlcipher_sqlite3ExprListCompare(pGroupBy, sSort.pOrderBy, -1)==0 ){
orderByGrp = 1;
@@ -141111,11 +148314,14 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Select(
** SELECT statement.
*/
pAggInfo = sqlcipher_sqlite3DbMallocZero(db, sizeof(*pAggInfo) );
- if( pAggInfo==0 ){
+ if( pAggInfo ){
+ sqlcipher_sqlite3ParserAddCleanup(pParse,
+ (void(*)(sqlcipher_sqlite3*,void*))agginfoFree, pAggInfo);
+ testcase( pParse->earlyCleanup );
+ }
+ if( db->mallocFailed ){
goto select_end;
}
- pAggInfo->pNext = pParse->pAggList;
- pParse->pAggList = pAggInfo;
pAggInfo->selId = p->selId;
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = pParse;
@@ -141145,7 +148351,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Select(
}
for(i=0; i<pAggInfo->nFunc; i++){
Expr *pExpr = pAggInfo->aFunc[i].pFExpr;
- assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
+ assert( ExprUseXList(pExpr) );
sNC.ncFlags |= NC_InAggFunc;
sqlcipher_sqlite3ExprAnalyzeAggList(&sNC, pExpr->x.pList);
#ifndef SQLITE_OMIT_WINDOWFUNC
@@ -141158,11 +148364,15 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Select(
}
pAggInfo->mxReg = pParse->nMem;
if( db->mallocFailed ) goto select_end;
-#if SELECTTRACE_ENABLED
- if( sqlcipher_sqlite3_unsupported_selecttrace & 0x400 ){
+#if TREETRACE_ENABLED
+ if( sqlcipher_sqlite3TreeTrace & 0x400 ){
int ii;
SELECTTRACE(0x400,pParse,p,("After aggregate analysis %p:\n", pAggInfo));
sqlcipher_sqlite3TreeViewSelect(0, p, 0);
+ if( minMaxFlag ){
+ sqlcipher_sqlite3DebugPrintf("MIN/MAX Optimization (0x%02x) adds:\n", minMaxFlag);
+ sqlcipher_sqlite3TreeViewExprList(0, pMinMaxOrderBy, 0, "ORDERBY");
+ }
for(ii=0; ii<pAggInfo->nColumn; ii++){
sqlcipher_sqlite3DebugPrintf("agg-column[%d] iMem=%d\n",
ii, pAggInfo->aCol[ii].iMem);
@@ -141190,6 +148400,22 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Select(
int addrSortingIdx; /* The OP_OpenEphemeral for the sorting index */
int addrReset; /* Subroutine for resetting the accumulator */
int regReset; /* Return address register for reset subroutine */
+ ExprList *pDistinct = 0;
+ u16 distFlag = 0;
+ int eDist = WHERE_DISTINCT_NOOP;
+
+ if( pAggInfo->nFunc==1
+ && pAggInfo->aFunc[0].iDistinct>=0
+ && ALWAYS(pAggInfo->aFunc[0].pFExpr!=0)
+ && ALWAYS(ExprUseXList(pAggInfo->aFunc[0].pFExpr))
+ && pAggInfo->aFunc[0].pFExpr->x.pList!=0
+ ){
+ Expr *pExpr = pAggInfo->aFunc[0].pFExpr->x.pList->a[0].pExpr;
+ pExpr = sqlcipher_sqlite3ExprDup(db, pExpr, 0);
+ pDistinct = sqlcipher_sqlite3ExprListDup(db, pGroupBy, 0);
+ pDistinct = sqlcipher_sqlite3ExprListAppend(pParse, pDistinct, pExpr);
+ distFlag = pDistinct ? (WHERE_WANT_DISTINCT|WHERE_AGG_DISTINCT) : 0;
+ }
/* If there is a GROUP BY clause we might need a sorting index to
** implement it. Allocate that sorting index now. If it turns out
@@ -141226,10 +148452,16 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Select(
*/
sqlcipher_sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
SELECTTRACE(1,pParse,p,("WhereBegin\n"));
- pWInfo = sqlcipher_sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, 0,
- WHERE_GROUPBY | (orderByGrp ? WHERE_SORTBYGROUP : 0), 0
+ pWInfo = sqlcipher_sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, pDistinct,
+ 0, (sDistinct.isTnct==2 ? WHERE_DISTINCTBY : WHERE_GROUPBY)
+ | (orderByGrp ? WHERE_SORTBYGROUP : 0) | distFlag, 0
);
- if( pWInfo==0 ) goto select_end;
+ if( pWInfo==0 ){
+ sqlcipher_sqlite3ExprListDelete(db, pDistinct);
+ goto select_end;
+ }
+ eDist = sqlcipher_sqlite3WhereIsDistinct(pWInfo);
+ SELECTTRACE(1,pParse,p,("WhereBegin returns\n"));
if( sqlcipher_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
@@ -141278,6 +148510,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Select(
sqlcipher_sqlite3VdbeAddOp2(v, OP_SorterInsert, pAggInfo->sortingIdx, regRecord);
sqlcipher_sqlite3ReleaseTempReg(pParse, regRecord);
sqlcipher_sqlite3ReleaseTempRange(pParse, regBase, nCol);
+ SELECTTRACE(1,pParse,p,("WhereEnd\n"));
sqlcipher_sqlite3WhereEnd(pWInfo);
pAggInfo->sortingIdxPTab = sortPTab = pParse->nTab++;
sortOut = sqlcipher_sqlite3GetTempReg(pParse);
@@ -141345,19 +148578,21 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Select(
** the current row
*/
sqlcipher_sqlite3VdbeJumpHere(v, addr1);
- updateAccumulator(pParse, iUseFlag, pAggInfo);
+ updateAccumulator(pParse, iUseFlag, pAggInfo, eDist);
sqlcipher_sqlite3VdbeAddOp2(v, OP_Integer, 1, iUseFlag);
VdbeComment((v, "indicate data in accumulator"));
/* End of the loop
*/
if( groupBySort ){
- sqlcipher_sqlite3VdbeAddOp2(v, OP_SorterNext, pAggInfo->sortingIdx, addrTopOfLoop);
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_SorterNext, pAggInfo->sortingIdx,addrTopOfLoop);
VdbeCoverage(v);
}else{
+ SELECTTRACE(1,pParse,p,("WhereEnd\n"));
sqlcipher_sqlite3WhereEnd(pWInfo);
sqlcipher_sqlite3VdbeChangeToNoop(v, addrSortingIdx);
}
+ sqlcipher_sqlite3ExprListDelete(db, pDistinct);
/* Output the final row of result
*/
@@ -141401,6 +148636,10 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Select(
VdbeComment((v, "indicate accumulator empty"));
sqlcipher_sqlite3VdbeAddOp1(v, OP_Return, regReset);
+ if( distFlag!=0 && eDist!=WHERE_DISTINCT_NOOP ){
+ struct AggInfo_func *pF = &pAggInfo->aFunc[0];
+ fixDistinctOpenEph(pParse, eDist, pF->iDistinct, pF->iDistAddr);
+ }
} /* endif pGroupBy. Begin aggregate queries without GROUP BY: */
else {
Table *pTab;
@@ -141464,7 +148703,9 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Select(
explainSimpleCount(pParse, pTab, pBest);
}else{
int regAcc = 0; /* "populate accumulators" flag */
- int addrSkip;
+ ExprList *pDistinct = 0;
+ u16 distFlag = 0;
+ int eDist;
/* If there are accumulator registers but no min() or max() functions
** without FILTER clauses, allocate register regAcc. Register regAcc
@@ -141488,6 +148729,10 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Select(
regAcc = ++pParse->nMem;
sqlcipher_sqlite3VdbeAddOp2(v, OP_Integer, 0, regAcc);
}
+ }else if( pAggInfo->nFunc==1 && pAggInfo->aFunc[0].iDistinct>=0 ){
+ assert( ExprUseXList(pAggInfo->aFunc[0].pFExpr) );
+ pDistinct = pAggInfo->aFunc[0].pFExpr->x.pList;
+ distFlag = pDistinct ? (WHERE_WANT_DISTINCT|WHERE_AGG_DISTINCT) : 0;
}
/* This case runs if the aggregate has no GROUP BY clause. The
@@ -141507,16 +148752,25 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Select(
SELECTTRACE(1,pParse,p,("WhereBegin\n"));
pWInfo = sqlcipher_sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMaxOrderBy,
- 0, minMaxFlag, 0);
+ pDistinct, 0, minMaxFlag|distFlag, 0);
if( pWInfo==0 ){
goto select_end;
}
- updateAccumulator(pParse, regAcc, pAggInfo);
+ SELECTTRACE(1,pParse,p,("WhereBegin returns\n"));
+ eDist = sqlcipher_sqlite3WhereIsDistinct(pWInfo);
+ updateAccumulator(pParse, regAcc, pAggInfo, eDist);
+ if( eDist!=WHERE_DISTINCT_NOOP ){
+ struct AggInfo_func *pF = pAggInfo->aFunc;
+ if( pF ){
+ fixDistinctOpenEph(pParse, eDist, pF->iDistinct, pF->iDistAddr);
+ }
+ }
+
if( regAcc ) sqlcipher_sqlite3VdbeAddOp2(v, OP_Integer, 1, regAcc);
- addrSkip = sqlcipher_sqlite3WhereOrderByLimitOptLabel(pWInfo);
- if( addrSkip!=sqlcipher_sqlite3WhereContinueLabel(pWInfo) ){
- sqlcipher_sqlite3VdbeGoto(v, addrSkip);
+ if( minMaxFlag ){
+ sqlcipher_sqlite3WhereMinMaxOptEarlyOut(v, pWInfo);
}
+ SELECTTRACE(1,pParse,p,("WhereEnd\n"));
sqlcipher_sqlite3WhereEnd(pWInfo);
finalizeAggFunctions(pParse, pAggInfo);
}
@@ -141556,29 +148810,29 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Select(
** successful coding of the SELECT.
*/
select_end:
+ assert( db->mallocFailed==0 || db->mallocFailed==1 );
+ assert( db->mallocFailed==0 || pParse->nErr!=0 );
sqlcipher_sqlite3ExprListDelete(db, pMinMaxOrderBy);
#ifdef SQLITE_DEBUG
if( pAggInfo && !db->mallocFailed ){
for(i=0; i<pAggInfo->nColumn; i++){
Expr *pExpr = pAggInfo->aCol[i].pCExpr;
- assert( pExpr!=0 || db->mallocFailed );
- if( pExpr==0 ) continue;
+ assert( pExpr!=0 );
assert( pExpr->pAggInfo==pAggInfo );
assert( pExpr->iAgg==i );
}
for(i=0; i<pAggInfo->nFunc; i++){
Expr *pExpr = pAggInfo->aFunc[i].pFExpr;
- assert( pExpr!=0 || db->mallocFailed );
- if( pExpr==0 ) continue;
+ assert( pExpr!=0 );
assert( pExpr->pAggInfo==pAggInfo );
assert( pExpr->iAgg==i );
}
}
#endif
-#if SELECTTRACE_ENABLED
+#if TREETRACE_ENABLED
SELECTTRACE(0x1,pParse,p,("end processing\n"));
- if( (sqlcipher_sqlite3_unsupported_selecttrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){
+ if( (sqlcipher_sqlite3TreeTrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){
sqlcipher_sqlite3TreeViewSelect(0, p, 0);
}
#endif
@@ -141839,28 +149093,48 @@ SQLITE_PRIVATE void sqlcipher_sqlite3DeleteTriggerStep(sqlcipher_sqlite3 *db, Tr
** pTab as well as the triggers lised in pTab->pTrigger.
*/
SQLITE_PRIVATE Trigger *sqlcipher_sqlite3TriggerList(Parse *pParse, Table *pTab){
- Schema * const pTmpSchema = pParse->db->aDb[1].pSchema;
- Trigger *pList = 0; /* List of triggers to return */
-
- if( pParse->disableTriggers ){
- return 0;
+ Schema *pTmpSchema; /* Schema of the pTab table */
+ Trigger *pList; /* List of triggers to return */
+ HashElem *p; /* Loop variable for TEMP triggers */
+
+ assert( pParse->disableTriggers==0 );
+ pTmpSchema = pParse->db->aDb[1].pSchema;
+ p = sqliteHashFirst(&pTmpSchema->trigHash);
+ pList = pTab->pTrigger;
+ while( p ){
+ Trigger *pTrig = (Trigger *)sqliteHashData(p);
+ if( pTrig->pTabSchema==pTab->pSchema
+ && pTrig->table
+ && 0==sqlcipher_sqlite3StrICmp(pTrig->table, pTab->zName)
+ && pTrig->pTabSchema!=pTmpSchema
+ ){
+ pTrig->pNext = pList;
+ pList = pTrig;
+ }else if( pTrig->op==TK_RETURNING ){
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ assert( pParse->db->pVtabCtx==0 );
+#endif
+ assert( pParse->bReturning );
+ assert( &(pParse->u1.pReturning->retTrig) == pTrig );
+ pTrig->table = pTab->zName;
+ pTrig->pTabSchema = pTab->pSchema;
+ pTrig->pNext = pList;
+ pList = pTrig;
+ }
+ p = sqliteHashNext(p);
}
-
- if( pTmpSchema!=pTab->pSchema ){
- HashElem *p;
- assert( sqlcipher_sqlite3SchemaMutexHeld(pParse->db, 0, pTmpSchema) );
- for(p=sqliteHashFirst(&pTmpSchema->trigHash); p; p=sqliteHashNext(p)){
- Trigger *pTrig = (Trigger *)sqliteHashData(p);
- if( pTrig->pTabSchema==pTab->pSchema
- && 0==sqlcipher_sqlite3StrICmp(pTrig->table, pTab->zName)
- ){
- pTrig->pNext = (pList ? pList : pTab->pTrigger);
- pList = pTrig;
- }
+#if 0
+ if( pList ){
+ Trigger *pX;
+ printf("Triggers for %s:", pTab->zName);
+ for(pX=pList; pX; pX=pX->pNext){
+ printf(" %s", pX->zName);
}
+ printf("\n");
+ fflush(stdout);
}
-
- return (pList ? pList : pTab->pTrigger);
+#endif
+ return pList;
}
/*
@@ -141987,14 +149261,14 @@ SQLITE_PRIVATE void sqlcipher_sqlite3BeginTrigger(
/* INSTEAD of triggers are only for views and views only support INSTEAD
** of triggers.
*/
- if( pTab->pSelect && tr_tm!=TK_INSTEAD ){
+ if( IsView(pTab) && tr_tm!=TK_INSTEAD ){
sqlcipher_sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S",
- (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName, 0);
+ (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName->a);
goto trigger_orphan_error;
}
- if( !pTab->pSelect && tr_tm==TK_INSTEAD ){
+ if( !IsView(pTab) && tr_tm==TK_INSTEAD ){
sqlcipher_sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF"
- " trigger on table: %S", pTableName, 0);
+ " trigger on table: %S", pTableName->a);
goto trigger_orphan_error;
}
@@ -142122,6 +149396,23 @@ SQLITE_PRIVATE void sqlcipher_sqlite3FinishTrigger(
Vdbe *v;
char *z;
+ /* If this is a new CREATE TABLE statement, and if shadow tables
+ ** are read-only, and the trigger makes a change to a shadow table,
+ ** then raise an error - do not allow the trigger to be created. */
+ if( sqlcipher_sqlite3ReadOnlyShadowTables(db) ){
+ TriggerStep *pStep;
+ for(pStep=pTrig->step_list; pStep; pStep=pStep->pNext){
+ if( pStep->zTarget!=0
+ && sqlcipher_sqlite3ShadowTableName(db, pStep->zTarget)
+ ){
+ sqlcipher_sqlite3ErrorMsg(pParse,
+ "trigger \"%s\" may not write to shadow table \"%s\"",
+ pTrig->zName, pStep->zTarget);
+ goto triggerfinish_cleanup;
+ }
+ }
+ }
+
/* Make an entry in the sqlite_schema table */
v = sqlcipher_sqlite3GetVdbe(pParse);
if( v==0 ) goto triggerfinish_cleanup;
@@ -142129,14 +149420,14 @@ SQLITE_PRIVATE void sqlcipher_sqlite3FinishTrigger(
z = sqlcipher_sqlite3DbStrNDup(db, (char*)pAll->z, pAll->n);
testcase( z==0 );
sqlcipher_sqlite3NestedParse(pParse,
- "INSERT INTO %Q." DFLT_SCHEMA_TABLE
+ "INSERT INTO %Q." LEGACY_SCHEMA_TABLE
" VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')",
db->aDb[iDb].zDbSName, zName,
pTrig->table, z);
sqlcipher_sqlite3DbFree(db, z);
sqlcipher_sqlite3ChangeCookie(pParse, iDb);
sqlcipher_sqlite3VdbeAddParseSchemaOp(v, iDb,
- sqlcipher_sqlite3MPrintf(db, "type='trigger' AND name='%q'", zName));
+ sqlcipher_sqlite3MPrintf(db, "type='trigger' AND name='%q'", zName), 0);
}
if( db->init.busy ){
@@ -142214,6 +149505,7 @@ static TriggerStep *triggerStepAllocate(
sqlcipher_sqlite3 *db = pParse->db;
TriggerStep *pTriggerStep;
+ if( pParse->nErr ) return 0;
pTriggerStep = sqlcipher_sqlite3DbMallocZero(db, sizeof(TriggerStep) + pName->n + 1);
if( pTriggerStep ){
char *z = (char*)&pTriggerStep[1];
@@ -142284,7 +149576,7 @@ SQLITE_PRIVATE TriggerStep *sqlcipher_sqlite3TriggerInsertStep(
SQLITE_PRIVATE TriggerStep *sqlcipher_sqlite3TriggerUpdateStep(
Parse *pParse, /* Parser */
Token *pTableName, /* Name of the table to be updated */
- SrcList *pFrom,
+ SrcList *pFrom, /* FROM clause for an UPDATE-FROM, or NULL */
ExprList *pEList, /* The SET clause: list of column and new values */
Expr *pWhere, /* The WHERE clause */
u8 orconf, /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */
@@ -142349,7 +149641,7 @@ SQLITE_PRIVATE TriggerStep *sqlcipher_sqlite3TriggerDeleteStep(
** Recursively delete a Trigger structure
*/
SQLITE_PRIVATE void sqlcipher_sqlite3DeleteTrigger(sqlcipher_sqlite3 *db, Trigger *pTrigger){
- if( pTrigger==0 ) return;
+ if( pTrigger==0 || pTrigger->bReturning ) return;
sqlcipher_sqlite3DeleteTriggerStep(db, pTrigger->step_list);
sqlcipher_sqlite3DbFree(db, pTrigger->zName);
sqlcipher_sqlite3DbFree(db, pTrigger->table);
@@ -142391,7 +149683,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3DropTrigger(Parse *pParse, SrcList *pName,
}
if( !pTrigger ){
if( !noErr ){
- sqlcipher_sqlite3ErrorMsg(pParse, "no such trigger: %S", pName, 0);
+ sqlcipher_sqlite3ErrorMsg(pParse, "no such trigger: %S", pName->a);
}else{
sqlcipher_sqlite3CodeVerifyNamedSchema(pParse, zDb);
}
@@ -142443,7 +149735,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTri
*/
if( (v = sqlcipher_sqlite3GetVdbe(pParse))!=0 ){
sqlcipher_sqlite3NestedParse(pParse,
- "DELETE FROM %Q." DFLT_SCHEMA_TABLE " WHERE name=%Q AND type='trigger'",
+ "DELETE FROM %Q." LEGACY_SCHEMA_TABLE " WHERE name=%Q AND type='trigger'",
db->aDb[iDb].zDbSName, pTrigger->zName
);
sqlcipher_sqlite3ChangeCookie(pParse, iDb);
@@ -142498,12 +149790,21 @@ static int checkColumnOverlap(IdList *pIdList, ExprList *pEList){
}
/*
+** Return true if any TEMP triggers exist
+*/
+static int tempTriggersExist(sqlcipher_sqlite3 *db){
+ if( NEVER(db->aDb[1].pSchema==0) ) return 0;
+ if( sqliteHashFirst(&db->aDb[1].pSchema->trigHash)==0 ) return 0;
+ return 1;
+}
+
+/*
** Return a list of all triggers on table pTab if there exists at least
** one trigger that must be fired when an operation of type 'op' is
** performed on the table, and, if that operation is an UPDATE, if at
** least one of the columns in pChanges is being modified.
*/
-SQLITE_PRIVATE Trigger *sqlcipher_sqlite3TriggersExist(
+static SQLITE_NOINLINE Trigger *triggersReallyExist(
Parse *pParse, /* Parse context */
Table *pTab, /* The table the contains the triggers */
int op, /* one of TK_DELETE, TK_INSERT, TK_UPDATE */
@@ -142514,20 +149815,74 @@ SQLITE_PRIVATE Trigger *sqlcipher_sqlite3TriggersExist(
Trigger *pList = 0;
Trigger *p;
- if( (pParse->db->flags & SQLITE_EnableTrigger)!=0 ){
- pList = sqlcipher_sqlite3TriggerList(pParse, pTab);
- }
- assert( pList==0 || IsVirtual(pTab)==0 );
- for(p=pList; p; p=p->pNext){
- if( p->op==op && checkColumnOverlap(p->pColumns, pChanges) ){
- mask |= p->tr_tm;
+ pList = sqlcipher_sqlite3TriggerList(pParse, pTab);
+ assert( pList==0 || IsVirtual(pTab)==0
+ || (pList->bReturning && pList->pNext==0) );
+ if( pList!=0 ){
+ p = pList;
+ if( (pParse->db->flags & SQLITE_EnableTrigger)==0
+ && pTab->pTrigger!=0
+ ){
+ /* The SQLITE_DBCONFIG_ENABLE_TRIGGER setting is off. That means that
+ ** only TEMP triggers are allowed. Truncate the pList so that it
+ ** includes only TEMP triggers */
+ if( pList==pTab->pTrigger ){
+ pList = 0;
+ goto exit_triggers_exist;
+ }
+ while( ALWAYS(p->pNext) && p->pNext!=pTab->pTrigger ) p = p->pNext;
+ p->pNext = 0;
+ p = pList;
}
+ do{
+ if( p->op==op && checkColumnOverlap(p->pColumns, pChanges) ){
+ mask |= p->tr_tm;
+ }else if( p->op==TK_RETURNING ){
+ /* The first time a RETURNING trigger is seen, the "op" value tells
+ ** us what time of trigger it should be. */
+ assert( sqlcipher_sqlite3IsToplevel(pParse) );
+ p->op = op;
+ if( IsVirtual(pTab) ){
+ if( op!=TK_INSERT ){
+ sqlcipher_sqlite3ErrorMsg(pParse,
+ "%s RETURNING is not available on virtual tables",
+ op==TK_DELETE ? "DELETE" : "UPDATE");
+ }
+ p->tr_tm = TRIGGER_BEFORE;
+ }else{
+ p->tr_tm = TRIGGER_AFTER;
+ }
+ mask |= p->tr_tm;
+ }else if( p->bReturning && p->op==TK_INSERT && op==TK_UPDATE
+ && sqlcipher_sqlite3IsToplevel(pParse) ){
+ /* Also fire a RETURNING trigger for an UPSERT */
+ mask |= p->tr_tm;
+ }
+ p = p->pNext;
+ }while( p );
}
+exit_triggers_exist:
if( pMask ){
*pMask = mask;
}
return (mask ? pList : 0);
}
+SQLITE_PRIVATE Trigger *sqlcipher_sqlite3TriggersExist(
+ Parse *pParse, /* Parse context */
+ Table *pTab, /* The table the contains the triggers */
+ int op, /* one of TK_DELETE, TK_INSERT, TK_UPDATE */
+ ExprList *pChanges, /* Columns that change in an UPDATE statement */
+ int *pMask /* OUT: Mask of TRIGGER_BEFORE|TRIGGER_AFTER */
+){
+ assert( pTab!=0 );
+ if( (pTab->pTrigger==0 && !tempTriggersExist(pParse->db))
+ || pParse->disableTriggers
+ ){
+ if( pMask ) *pMask = 0;
+ return 0;
+ }
+ return triggersReallyExist(pParse,pTab,op,pChanges,pMask);
+}
/*
** Convert the pStep->zTarget string into a SrcList and return a pointer
@@ -142557,6 +149912,14 @@ SQLITE_PRIVATE SrcList *sqlcipher_sqlite3TriggerStepSrc(
}
if( pStep->pFrom ){
SrcList *pDup = sqlcipher_sqlite3SrcListDup(db, pStep->pFrom, 0);
+ if( pDup && pDup->nSrc>1 && !IN_RENAME_OBJECT ){
+ Select *pSubquery;
+ Token as;
+ pSubquery = sqlcipher_sqlite3SelectNew(pParse,0,pDup,0,0,0,0,SF_NestedFrom,0);
+ as.n = 0;
+ as.z = 0;
+ pDup = sqlcipher_sqlite3SrcListAppendFromTerm(pParse,0,0,0,&as,pSubquery,0);
+ }
pSrc = sqlcipher_sqlite3SrcListAppendList(pParse, pSrc, pDup);
}
}else{
@@ -142566,6 +149929,146 @@ SQLITE_PRIVATE SrcList *sqlcipher_sqlite3TriggerStepSrc(
}
/*
+** Return true if the pExpr term from the RETURNING clause argument
+** list is of the form "*". Raise an error if the terms if of the
+** form "table.*".
+*/
+static int isAsteriskTerm(
+ Parse *pParse, /* Parsing context */
+ Expr *pTerm /* A term in the RETURNING clause */
+){
+ assert( pTerm!=0 );
+ if( pTerm->op==TK_ASTERISK ) return 1;
+ if( pTerm->op!=TK_DOT ) return 0;
+ assert( pTerm->pRight!=0 );
+ assert( pTerm->pLeft!=0 );
+ if( pTerm->pRight->op!=TK_ASTERISK ) return 0;
+ sqlcipher_sqlite3ErrorMsg(pParse, "RETURNING may not use \"TABLE.*\" wildcards");
+ return 1;
+}
+
+/* The input list pList is the list of result set terms from a RETURNING
+** clause. The table that we are returning from is pTab.
+**
+** This routine makes a copy of the pList, and at the same time expands
+** any "*" wildcards to be the complete set of columns from pTab.
+*/
+static ExprList *sqlcipher_sqlite3ExpandReturning(
+ Parse *pParse, /* Parsing context */
+ ExprList *pList, /* The arguments to RETURNING */
+ Table *pTab /* The table being updated */
+){
+ ExprList *pNew = 0;
+ sqlcipher_sqlite3 *db = pParse->db;
+ int i;
+
+ for(i=0; i<pList->nExpr; i++){
+ Expr *pOldExpr = pList->a[i].pExpr;
+ if( NEVER(pOldExpr==0) ) continue;
+ if( isAsteriskTerm(pParse, pOldExpr) ){
+ int jj;
+ for(jj=0; jj<pTab->nCol; jj++){
+ Expr *pNewExpr;
+ if( IsHiddenColumn(pTab->aCol+jj) ) continue;
+ pNewExpr = sqlcipher_sqlite3Expr(db, TK_ID, pTab->aCol[jj].zCnName);
+ pNew = sqlcipher_sqlite3ExprListAppend(pParse, pNew, pNewExpr);
+ if( !db->mallocFailed ){
+ struct ExprList_item *pItem = &pNew->a[pNew->nExpr-1];
+ pItem->zEName = sqlcipher_sqlite3DbStrDup(db, pTab->aCol[jj].zCnName);
+ pItem->fg.eEName = ENAME_NAME;
+ }
+ }
+ }else{
+ Expr *pNewExpr = sqlcipher_sqlite3ExprDup(db, pOldExpr, 0);
+ pNew = sqlcipher_sqlite3ExprListAppend(pParse, pNew, pNewExpr);
+ if( !db->mallocFailed && ALWAYS(pList->a[i].zEName!=0) ){
+ struct ExprList_item *pItem = &pNew->a[pNew->nExpr-1];
+ pItem->zEName = sqlcipher_sqlite3DbStrDup(db, pList->a[i].zEName);
+ pItem->fg.eEName = pList->a[i].fg.eEName;
+ }
+ }
+ }
+ return pNew;
+}
+
+/*
+** Generate code for the RETURNING trigger. Unlike other triggers
+** that invoke a subprogram in the bytecode, the code for RETURNING
+** is generated in-line.
+*/
+static void codeReturningTrigger(
+ Parse *pParse, /* Parse context */
+ Trigger *pTrigger, /* The trigger step that defines the RETURNING */
+ Table *pTab, /* The table to code triggers from */
+ int regIn /* The first in an array of registers */
+){
+ Vdbe *v = pParse->pVdbe;
+ sqlcipher_sqlite3 *db = pParse->db;
+ ExprList *pNew;
+ Returning *pReturning;
+ Select sSelect;
+ SrcList sFrom;
+
+ assert( v!=0 );
+ assert( pParse->bReturning );
+ assert( db->pParse==pParse );
+ pReturning = pParse->u1.pReturning;
+ assert( pTrigger == &(pReturning->retTrig) );
+ memset(&sSelect, 0, sizeof(sSelect));
+ memset(&sFrom, 0, sizeof(sFrom));
+ sSelect.pEList = sqlcipher_sqlite3ExprListDup(db, pReturning->pReturnEL, 0);
+ sSelect.pSrc = &sFrom;
+ sFrom.nSrc = 1;
+ sFrom.a[0].pTab = pTab;
+ sFrom.a[0].iCursor = -1;
+ sqlcipher_sqlite3SelectPrep(pParse, &sSelect, 0);
+ if( pParse->nErr==0 ){
+ assert( db->mallocFailed==0 );
+ sqlcipher_sqlite3GenerateColumnNames(pParse, &sSelect);
+ }
+ sqlcipher_sqlite3ExprListDelete(db, sSelect.pEList);
+ pNew = sqlcipher_sqlite3ExpandReturning(pParse, pReturning->pReturnEL, pTab);
+ if( !db->mallocFailed ){
+ NameContext sNC;
+ memset(&sNC, 0, sizeof(sNC));
+ if( pReturning->nRetCol==0 ){
+ pReturning->nRetCol = pNew->nExpr;
+ pReturning->iRetCur = pParse->nTab++;
+ }
+ sNC.pParse = pParse;
+ sNC.uNC.iBaseReg = regIn;
+ sNC.ncFlags = NC_UBaseReg;
+ pParse->eTriggerOp = pTrigger->op;
+ pParse->pTriggerTab = pTab;
+ if( sqlcipher_sqlite3ResolveExprListNames(&sNC, pNew)==SQLITE_OK
+ && ALWAYS(!db->mallocFailed)
+ ){
+ int i;
+ int nCol = pNew->nExpr;
+ int reg = pParse->nMem+1;
+ pParse->nMem += nCol+2;
+ pReturning->iRetReg = reg;
+ for(i=0; i<nCol; i++){
+ Expr *pCol = pNew->a[i].pExpr;
+ assert( pCol!=0 ); /* Due to !db->mallocFailed ~9 lines above */
+ sqlcipher_sqlite3ExprCodeFactorable(pParse, pCol, reg+i);
+ if( sqlcipher_sqlite3ExprAffinity(pCol)==SQLITE_AFF_REAL ){
+ sqlcipher_sqlite3VdbeAddOp1(v, OP_RealAffinity, reg+i);
+ }
+ }
+ sqlcipher_sqlite3VdbeAddOp3(v, OP_MakeRecord, reg, i, reg+i);
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_NewRowid, pReturning->iRetCur, reg+i+1);
+ sqlcipher_sqlite3VdbeAddOp3(v, OP_Insert, pReturning->iRetCur, reg+i, reg+i+1);
+ }
+ }
+ sqlcipher_sqlite3ExprListDelete(db, pNew);
+ pParse->eTriggerOp = 0;
+ pParse->pTriggerTab = 0;
+}
+
+
+
+/*
** Generate VDBE code for the statements inside the body of a single
** trigger.
*/
@@ -142614,6 +150117,7 @@ static int codeTriggerProgram(
sqlcipher_sqlite3ExprDup(db, pStep->pWhere, 0),
pParse->eOrconf, 0, 0, 0
);
+ sqlcipher_sqlite3VdbeAddOp0(v, OP_ResetCount);
break;
}
case TK_INSERT: {
@@ -142624,6 +150128,7 @@ static int codeTriggerProgram(
pParse->eOrconf,
sqlcipher_sqlite3UpsertDup(db, pStep->pUpsert)
);
+ sqlcipher_sqlite3VdbeAddOp0(v, OP_ResetCount);
break;
}
case TK_DELETE: {
@@ -142631,6 +150136,7 @@ static int codeTriggerProgram(
sqlcipher_sqlite3TriggerStepSrc(pParse, pStep),
sqlcipher_sqlite3ExprDup(db, pStep->pWhere, 0), 0, 0
);
+ sqlcipher_sqlite3VdbeAddOp0(v, OP_ResetCount);
break;
}
default: assert( pStep->op==TK_SELECT ); {
@@ -142642,9 +150148,6 @@ static int codeTriggerProgram(
break;
}
}
- if( pStep->op!=TK_SELECT ){
- sqlcipher_sqlite3VdbeAddOp0(v, OP_ResetCount);
- }
}
return 0;
@@ -142702,8 +150205,8 @@ static TriggerPrg *codeRowTrigger(
Vdbe *v; /* Temporary VM */
NameContext sNC; /* Name context for sub-vdbe */
SubProgram *pProgram = 0; /* Sub-vdbe for trigger program */
- Parse *pSubParse; /* Parse context for sub-vdbe */
int iEndTrigger = 0; /* Label to jump to if WHEN is false */
+ Parse sSubParse; /* Parse context for sub-vdbe */
assert( pTrigger->zName==0 || pTab==tableOfTrigger(pTrigger) );
assert( pTop->pVdbe );
@@ -142725,19 +150228,17 @@ static TriggerPrg *codeRowTrigger(
/* Allocate and populate a new Parse context to use for coding the
** trigger sub-program. */
- pSubParse = sqlcipher_sqlite3StackAllocZero(db, sizeof(Parse));
- if( !pSubParse ) return 0;
+ sqlcipher_sqlite3ParseObjectInit(&sSubParse, db);
memset(&sNC, 0, sizeof(sNC));
- sNC.pParse = pSubParse;
- pSubParse->db = db;
- pSubParse->pTriggerTab = pTab;
- pSubParse->pToplevel = pTop;
- pSubParse->zAuthContext = pTrigger->zName;
- pSubParse->eTriggerOp = pTrigger->op;
- pSubParse->nQueryLoop = pParse->nQueryLoop;
- pSubParse->disableVtab = pParse->disableVtab;
-
- v = sqlcipher_sqlite3GetVdbe(pSubParse);
+ sNC.pParse = &sSubParse;
+ sSubParse.pTriggerTab = pTab;
+ sSubParse.pToplevel = pTop;
+ sSubParse.zAuthContext = pTrigger->zName;
+ sSubParse.eTriggerOp = pTrigger->op;
+ sSubParse.nQueryLoop = pParse->nQueryLoop;
+ sSubParse.disableVtab = pParse->disableVtab;
+
+ v = sqlcipher_sqlite3GetVdbe(&sSubParse);
if( v ){
VdbeComment((v, "Start: %s.%s (%s %s%s%s ON %s)",
pTrigger->zName, onErrorText(orconf),
@@ -142760,17 +150261,17 @@ static TriggerPrg *codeRowTrigger(
** OP_Halt inserted at the end of the program. */
if( pTrigger->pWhen ){
pWhen = sqlcipher_sqlite3ExprDup(db, pTrigger->pWhen, 0);
- if( SQLITE_OK==sqlcipher_sqlite3ResolveExprNames(&sNC, pWhen)
- && db->mallocFailed==0
+ if( db->mallocFailed==0
+ && SQLITE_OK==sqlcipher_sqlite3ResolveExprNames(&sNC, pWhen)
){
- iEndTrigger = sqlcipher_sqlite3VdbeMakeLabel(pSubParse);
- sqlcipher_sqlite3ExprIfFalse(pSubParse, pWhen, iEndTrigger, SQLITE_JUMPIFNULL);
+ iEndTrigger = sqlcipher_sqlite3VdbeMakeLabel(&sSubParse);
+ sqlcipher_sqlite3ExprIfFalse(&sSubParse, pWhen, iEndTrigger, SQLITE_JUMPIFNULL);
}
sqlcipher_sqlite3ExprDelete(db, pWhen);
}
/* Code the trigger program into the sub-vdbe. */
- codeTriggerProgram(pSubParse, pTrigger->step_list, orconf);
+ codeTriggerProgram(&sSubParse, pTrigger->step_list, orconf);
/* Insert an OP_Halt at the end of the sub-program. */
if( iEndTrigger ){
@@ -142778,24 +150279,24 @@ static TriggerPrg *codeRowTrigger(
}
sqlcipher_sqlite3VdbeAddOp0(v, OP_Halt);
VdbeComment((v, "End: %s.%s", pTrigger->zName, onErrorText(orconf)));
+ transferParseError(pParse, &sSubParse);
- transferParseError(pParse, pSubParse);
- if( db->mallocFailed==0 && pParse->nErr==0 ){
+ if( pParse->nErr==0 ){
+ assert( db->mallocFailed==0 );
pProgram->aOp = sqlcipher_sqlite3VdbeTakeOpArray(v, &pProgram->nOp, &pTop->nMaxArg);
}
- pProgram->nMem = pSubParse->nMem;
- pProgram->nCsr = pSubParse->nTab;
+ pProgram->nMem = sSubParse.nMem;
+ pProgram->nCsr = sSubParse.nTab;
pProgram->token = (void *)pTrigger;
- pPrg->aColmask[0] = pSubParse->oldmask;
- pPrg->aColmask[1] = pSubParse->newmask;
+ pPrg->aColmask[0] = sSubParse.oldmask;
+ pPrg->aColmask[1] = sSubParse.newmask;
sqlcipher_sqlite3VdbeDelete(v);
+ }else{
+ transferParseError(pParse, &sSubParse);
}
- assert( !pSubParse->pAinc && !pSubParse->pZombieTab );
- assert( !pSubParse->pTriggerPrg && !pSubParse->nMaxArg );
- sqlcipher_sqlite3ParserReset(pSubParse);
- sqlcipher_sqlite3StackFree(db, pSubParse);
-
+ assert( !sSubParse.pTriggerPrg && !sSubParse.nMaxArg );
+ sqlcipher_sqlite3ParseObjectReset(&sSubParse);
return pPrg;
}
@@ -142828,6 +150329,7 @@ static TriggerPrg *getRowTrigger(
/* If an existing TriggerPrg could not be located, create a new one. */
if( !pPrg ){
pPrg = codeRowTrigger(pParse, pTrigger, pTab, orconf);
+ pParse->db->errByteOffset = -1;
}
return pPrg;
@@ -142850,7 +150352,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3CodeRowTriggerDirect(
Vdbe *v = sqlcipher_sqlite3GetVdbe(pParse); /* Main VM */
TriggerPrg *pPrg;
pPrg = getRowTrigger(pParse, p, pTab, orconf);
- assert( pPrg || pParse->nErr || pParse->db->mallocFailed );
+ assert( pPrg || pParse->nErr );
/* Code the OP_Program opcode in the parent VDBE. P4 of the OP_Program
** is a pointer to the sub-vdbe containing the trigger program. */
@@ -142893,7 +150395,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3CodeRowTriggerDirect(
** ... ...
** reg+N OLD.* value of right-most column of pTab
** reg+N+1 NEW.rowid
-** reg+N+2 OLD.* value of left-most column of pTab
+** reg+N+2 NEW.* value of left-most column of pTab
** ... ...
** reg+N+N+1 NEW.* value of right-most column of pTab
**
@@ -142938,12 +150440,20 @@ SQLITE_PRIVATE void sqlcipher_sqlite3CodeRowTrigger(
assert( p->pSchema==p->pTabSchema
|| p->pSchema==pParse->db->aDb[1].pSchema );
- /* Determine whether we should code this trigger */
- if( p->op==op
+ /* Determine whether we should code this trigger. One of two choices:
+ ** 1. The trigger is an exact match to the current DML statement
+ ** 2. This is a RETURNING trigger for INSERT but we are currently
+ ** doing the UPDATE part of an UPSERT.
+ */
+ if( (p->op==op || (p->bReturning && p->op==TK_INSERT && op==TK_UPDATE))
&& p->tr_tm==tr_tm
&& checkColumnOverlap(p->pColumns, pChanges)
){
- sqlcipher_sqlite3CodeRowTriggerDirect(pParse, p, pTab, reg, orconf, ignoreJump);
+ if( !p->bReturning ){
+ sqlcipher_sqlite3CodeRowTriggerDirect(pParse, p, pTab, reg, orconf, ignoreJump);
+ }else if( sqlcipher_sqlite3IsToplevel(pParse) ){
+ codeReturningTrigger(pParse, p, pTab, reg);
+ }
}
}
}
@@ -142988,13 +150498,18 @@ SQLITE_PRIVATE u32 sqlcipher_sqlite3TriggerColmask(
assert( isNew==1 || isNew==0 );
for(p=pTrigger; p; p=p->pNext){
- if( p->op==op && (tr_tm&p->tr_tm)
+ if( p->op==op
+ && (tr_tm&p->tr_tm)
&& checkColumnOverlap(p->pColumns,pChanges)
){
- TriggerPrg *pPrg;
- pPrg = getRowTrigger(pParse, p, pTab, orconf);
- if( pPrg ){
- mask |= pPrg->aColmask[isNew];
+ if( p->bReturning ){
+ mask = 0xffffffff;
+ }else{
+ TriggerPrg *pPrg;
+ pPrg = getRowTrigger(pParse, p, pTab, orconf);
+ if( pPrg ){
+ mask |= pPrg->aColmask[isNew];
+ }
}
}
}
@@ -143068,13 +150583,14 @@ static void updateVirtualTable(
*/
SQLITE_PRIVATE void sqlcipher_sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){
assert( pTab!=0 );
- if( !pTab->pSelect ){
+ if( !IsView(pTab) ){
sqlcipher_sqlite3_value *pValue = 0;
u8 enc = ENC(sqlcipher_sqlite3VdbeDb(v));
Column *pCol = &pTab->aCol[i];
- VdbeComment((v, "%s.%s", pTab->zName, pCol->zName));
+ VdbeComment((v, "%s.%s", pTab->zName, pCol->zCnName));
assert( i<pTab->nCol );
- sqlcipher_sqlite3ValueFromExpr(sqlcipher_sqlite3VdbeDb(v), pCol->pDflt, enc,
+ sqlcipher_sqlite3ValueFromExpr(sqlcipher_sqlite3VdbeDb(v),
+ sqlcipher_sqlite3ColumnExpr(pTab,pCol), enc,
pCol->affinity, &pValue);
if( pValue ){
sqlcipher_sqlite3VdbeAppendP4(v, pValue, P4_MEM);
@@ -143228,6 +150744,7 @@ static void updateFromSelect(
assert( pTabList->nSrc>1 );
if( pSrc ){
+ pSrc->a[0].fg.notCte = 1;
pSrc->a[0].iCursor = -1;
pSrc->a[0].pTab->nTabRef--;
pSrc->a[0].pTab = 0;
@@ -143243,7 +150760,7 @@ static void updateFromSelect(
pList = sqlcipher_sqlite3ExprListAppend(pParse, pList, pNew);
}
eDest = IsVirtual(pTab) ? SRT_Table : SRT_Upfrom;
- }else if( pTab->pSelect ){
+ }else if( IsView(pTab) ){
for(i=0; i<pTab->nCol; i++){
pList = sqlcipher_sqlite3ExprListAppend(pParse, pList, exprRowColumn(pParse, i));
}
@@ -143257,7 +150774,8 @@ static void updateFromSelect(
}
#endif
}
- if( ALWAYS(pChanges) ){
+ assert( pChanges!=0 || pParse->db->mallocFailed );
+ if( pChanges ){
for(i=0; i<pChanges->nExpr; i++){
pList = sqlcipher_sqlite3ExprListAppend(pParse, pList,
sqlcipher_sqlite3ExprDup(db, pChanges->a[i].pExpr, 0)
@@ -143265,8 +150783,9 @@ static void updateFromSelect(
}
}
pSelect = sqlcipher_sqlite3SelectNew(pParse, pList,
- pSrc, pWhere2, pGrp, 0, pOrderBy2, SF_UpdateFrom|SF_IncludeHidden, pLimit2
+ pSrc, pWhere2, pGrp, 0, pOrderBy2, SF_UFSrcCheck|SF_IncludeHidden, pLimit2
);
+ if( pSelect ) pSelect->selFlags |= SF_OrderByReqd;
sqlcipher_sqlite3SelectDestInit(&dest, eDest, iEph);
dest.iSDParm2 = (pPk ? pPk->nKeyCol : -1);
sqlcipher_sqlite3Select(pParse, pSelect, &dest);
@@ -143351,9 +150870,11 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Update(
memset(&sContext, 0, sizeof(sContext));
db = pParse->db;
- if( pParse->nErr || db->mallocFailed ){
+ assert( db->pParse==pParse );
+ if( pParse->nErr ){
goto update_cleanup;
}
+ assert( db->mallocFailed==0 );
/* Locate the table which we want to update.
*/
@@ -143366,7 +150887,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Update(
*/
#ifndef SQLITE_OMIT_TRIGGER
pTrigger = sqlcipher_sqlite3TriggersExist(pParse, pTab, TK_UPDATE, pChanges, &tmask);
- isView = pTab->pSelect!=0;
+ isView = IsView(pTab);
assert( pTrigger || tmask==0 );
#else
# define pTrigger 0
@@ -143378,6 +150899,14 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Update(
# define isView 0
#endif
+#if TREETRACE_ENABLED
+ if( sqlcipher_sqlite3TreeTrace & 0x10000 ){
+ sqlcipher_sqlite3TreeViewLine(0, "In sqlcipher_sqlite3Update() at %s:%d", __FILE__, __LINE__);
+ sqlcipher_sqlite3TreeViewUpdate(pParse->pWith, pTabList, pChanges, pWhere,
+ onError, pOrderBy, pLimit, pUpsert, pTrigger);
+ }
+#endif
+
/* If there was a FROM clause, set nChangeFrom to the number of expressions
** in the change-list. Otherwise, set it to 0. There cannot be a FROM
** clause if this function is being called to generate code for part of
@@ -143455,13 +150984,16 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Update(
*/
chngRowid = chngPk = 0;
for(i=0; i<pChanges->nExpr; i++){
+ u8 hCol = sqlcipher_sqlite3StrIHash(pChanges->a[i].zEName);
/* If this is an UPDATE with a FROM clause, do not resolve expressions
** here. The call to sqlcipher_sqlite3Select() below will do that. */
if( nChangeFrom==0 && sqlcipher_sqlite3ResolveExprNames(&sNC, pChanges->a[i].pExpr) ){
goto update_cleanup;
}
for(j=0; j<pTab->nCol; j++){
- if( sqlcipher_sqlite3StrICmp(pTab->aCol[j].zName, pChanges->a[i].zEName)==0 ){
+ if( pTab->aCol[j].hName==hCol
+ && sqlcipher_sqlite3StrICmp(pTab->aCol[j].zCnName, pChanges->a[i].zEName)==0
+ ){
if( j==pTab->iPKey ){
chngRowid = 1;
pRowidExpr = pChanges->a[i].pExpr;
@@ -143475,7 +151007,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Update(
testcase( pTab->aCol[j].colFlags & COLFLAG_STORED );
sqlcipher_sqlite3ErrorMsg(pParse,
"cannot UPDATE generated column \"%s\"",
- pTab->aCol[j].zName);
+ pTab->aCol[j].zCnName);
goto update_cleanup;
}
#endif
@@ -143499,7 +151031,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Update(
{
int rc;
rc = sqlcipher_sqlite3AuthCheck(pParse, SQLITE_UPDATE, pTab->zName,
- j<0 ? "ROWID" : pTab->aCol[j].zName,
+ j<0 ? "ROWID" : pTab->aCol[j].zCnName,
db->aDb[iDb].zDbSName);
if( rc==SQLITE_DENY ){
goto update_cleanup;
@@ -143531,8 +151063,10 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Update(
for(i=0; i<pTab->nCol; i++){
if( aXRef[i]>=0 ) continue;
if( (pTab->aCol[i].colFlags & COLFLAG_GENERATED)==0 ) continue;
- if( sqlcipher_sqlite3ExprReferencesUpdatedColumn(pTab->aCol[i].pDflt,
- aXRef, chngRowid) ){
+ if( sqlcipher_sqlite3ExprReferencesUpdatedColumn(
+ sqlcipher_sqlite3ColumnExpr(pTab, &pTab->aCol[i]),
+ aXRef, chngRowid)
+ ){
aXRef[i] = 99999;
bProgress = 1;
}
@@ -143651,6 +151185,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Update(
if( (db->flags&SQLITE_CountRows)!=0
&& !pParse->pTriggerTab
&& !pParse->nested
+ && !pParse->bReturning
&& pUpsert==0
){
regRowCount = ++pParse->nMem;
@@ -143719,7 +151254,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Update(
if( !pParse->nested && !pTrigger && !hasFK && !chngKey && !bReplace ){
flags |= WHERE_ONEPASS_MULTIROW;
}
- pWInfo = sqlcipher_sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, flags,iIdxCur);
+ pWInfo = sqlcipher_sqlite3WhereBegin(pParse, pTabList, pWhere,0,0,0,flags,iIdxCur);
if( pWInfo==0 ) goto update_cleanup;
/* A one-pass strategy that might update more than one row may not
@@ -143806,7 +151341,12 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Update(
/* Top of the update loop */
if( eOnePass!=ONEPASS_OFF ){
- if( !isView && aiCurOnePass[0]!=iDataCur && aiCurOnePass[1]!=iDataCur ){
+ if( aiCurOnePass[0]!=iDataCur
+ && aiCurOnePass[1]!=iDataCur
+#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
+ && !isView
+#endif
+ ){
assert( pPk );
sqlcipher_sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey,nKey);
VdbeCoverage(v);
@@ -144011,7 +151551,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Update(
}else{
sqlcipher_sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue,regOldRowid);
}
- VdbeCoverageNeverTaken(v);
+ VdbeCoverage(v);
}
/* Do FK constraint checks. */
@@ -144114,9 +151654,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Update(
** that information.
*/
if( regRowCount ){
- sqlcipher_sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1);
- sqlcipher_sqlite3VdbeSetNumCols(v, 1);
- sqlcipher_sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows updated", SQLITE_STATIC);
+ sqlcipher_sqlite3CodeChangeCount(v, regRowCount, "rows updated");
}
update_cleanup:
@@ -144238,7 +151776,9 @@ static void updateVirtualTable(
regRowid = ++pParse->nMem;
/* Start scanning the virtual table */
- pWInfo = sqlcipher_sqlite3WhereBegin(pParse, pSrc,pWhere,0,0,WHERE_ONEPASS_DESIRED,0);
+ pWInfo = sqlcipher_sqlite3WhereBegin(
+ pParse, pSrc, pWhere, 0, 0, 0, WHERE_ONEPASS_DESIRED, 0
+ );
if( pWInfo==0 ) return;
/* Populate the argument registers. */
@@ -144349,16 +151889,23 @@ static void updateVirtualTable(
/*
** Free a list of Upsert objects
*/
-SQLITE_PRIVATE void sqlcipher_sqlite3UpsertDelete(sqlcipher_sqlite3 *db, Upsert *p){
- if( p ){
+static void SQLITE_NOINLINE upsertDelete(sqlcipher_sqlite3 *db, Upsert *p){
+ do{
+ Upsert *pNext = p->pNextUpsert;
sqlcipher_sqlite3ExprListDelete(db, p->pUpsertTarget);
sqlcipher_sqlite3ExprDelete(db, p->pUpsertTargetWhere);
sqlcipher_sqlite3ExprListDelete(db, p->pUpsertSet);
sqlcipher_sqlite3ExprDelete(db, p->pUpsertWhere);
+ sqlcipher_sqlite3DbFree(db, p->pToFree);
sqlcipher_sqlite3DbFree(db, p);
- }
+ p = pNext;
+ }while( p );
+}
+SQLITE_PRIVATE void sqlcipher_sqlite3UpsertDelete(sqlcipher_sqlite3 *db, Upsert *p){
+ if( p ) upsertDelete(db, p);
}
+
/*
** Duplicate an Upsert object.
*/
@@ -144368,7 +151915,8 @@ SQLITE_PRIVATE Upsert *sqlcipher_sqlite3UpsertDup(sqlcipher_sqlite3 *db, Upsert
sqlcipher_sqlite3ExprListDup(db, p->pUpsertTarget, 0),
sqlcipher_sqlite3ExprDup(db, p->pUpsertTargetWhere, 0),
sqlcipher_sqlite3ExprListDup(db, p->pUpsertSet, 0),
- sqlcipher_sqlite3ExprDup(db, p->pUpsertWhere, 0)
+ sqlcipher_sqlite3ExprDup(db, p->pUpsertWhere, 0),
+ sqlcipher_sqlite3UpsertDup(db, p->pNextUpsert)
);
}
@@ -144380,22 +151928,25 @@ SQLITE_PRIVATE Upsert *sqlcipher_sqlite3UpsertNew(
ExprList *pTarget, /* Target argument to ON CONFLICT, or NULL */
Expr *pTargetWhere, /* Optional WHERE clause on the target */
ExprList *pSet, /* UPDATE columns, or NULL for a DO NOTHING */
- Expr *pWhere /* WHERE clause for the ON CONFLICT UPDATE */
+ Expr *pWhere, /* WHERE clause for the ON CONFLICT UPDATE */
+ Upsert *pNext /* Next ON CONFLICT clause in the list */
){
Upsert *pNew;
- pNew = sqlcipher_sqlite3DbMallocRaw(db, sizeof(Upsert));
+ pNew = sqlcipher_sqlite3DbMallocZero(db, sizeof(Upsert));
if( pNew==0 ){
sqlcipher_sqlite3ExprListDelete(db, pTarget);
sqlcipher_sqlite3ExprDelete(db, pTargetWhere);
sqlcipher_sqlite3ExprListDelete(db, pSet);
sqlcipher_sqlite3ExprDelete(db, pWhere);
+ sqlcipher_sqlite3UpsertDelete(db, pNext);
return 0;
}else{
pNew->pUpsertTarget = pTarget;
pNew->pUpsertTargetWhere = pTargetWhere;
pNew->pUpsertSet = pSet;
pNew->pUpsertWhere = pWhere;
- pNew->pUpsertIdx = 0;
+ pNew->isDoUpdate = pSet!=0;
+ pNew->pNextUpsert = pNext;
}
return pNew;
}
@@ -144420,6 +151971,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3UpsertAnalyzeTarget(
Expr *pTerm; /* One term of the conflict-target clause */
NameContext sNC; /* Context for resolving symbolic names */
Expr sCol[2]; /* Index column converted into an Expr */
+ int nClause = 0; /* Counter of ON CONFLICT clauses */
assert( pTabList->nSrc==1 );
assert( pTabList->a[0].pTab!=0 );
@@ -144433,87 +151985,131 @@ SQLITE_PRIVATE int sqlcipher_sqlite3UpsertAnalyzeTarget(
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = pParse;
sNC.pSrcList = pTabList;
- rc = sqlcipher_sqlite3ResolveExprListNames(&sNC, pUpsert->pUpsertTarget);
- if( rc ) return rc;
- rc = sqlcipher_sqlite3ResolveExprNames(&sNC, pUpsert->pUpsertTargetWhere);
- if( rc ) return rc;
+ for(; pUpsert && pUpsert->pUpsertTarget;
+ pUpsert=pUpsert->pNextUpsert, nClause++){
+ rc = sqlcipher_sqlite3ResolveExprListNames(&sNC, pUpsert->pUpsertTarget);
+ if( rc ) return rc;
+ rc = sqlcipher_sqlite3ResolveExprNames(&sNC, pUpsert->pUpsertTargetWhere);
+ if( rc ) return rc;
- /* Check to see if the conflict target matches the rowid. */
- pTab = pTabList->a[0].pTab;
- pTarget = pUpsert->pUpsertTarget;
- iCursor = pTabList->a[0].iCursor;
- if( HasRowid(pTab)
- && pTarget->nExpr==1
- && (pTerm = pTarget->a[0].pExpr)->op==TK_COLUMN
- && pTerm->iColumn==XN_ROWID
- ){
- /* The conflict-target is the rowid of the primary table */
- assert( pUpsert->pUpsertIdx==0 );
- return SQLITE_OK;
- }
+ /* Check to see if the conflict target matches the rowid. */
+ pTab = pTabList->a[0].pTab;
+ pTarget = pUpsert->pUpsertTarget;
+ iCursor = pTabList->a[0].iCursor;
+ if( HasRowid(pTab)
+ && pTarget->nExpr==1
+ && (pTerm = pTarget->a[0].pExpr)->op==TK_COLUMN
+ && pTerm->iColumn==XN_ROWID
+ ){
+ /* The conflict-target is the rowid of the primary table */
+ assert( pUpsert->pUpsertIdx==0 );
+ continue;
+ }
- /* Initialize sCol[0..1] to be an expression parse tree for a
- ** single column of an index. The sCol[0] node will be the TK_COLLATE
- ** operator and sCol[1] will be the TK_COLUMN operator. Code below
- ** will populate the specific collation and column number values
- ** prior to comparing against the conflict-target expression.
- */
- memset(sCol, 0, sizeof(sCol));
- sCol[0].op = TK_COLLATE;
- sCol[0].pLeft = &sCol[1];
- sCol[1].op = TK_COLUMN;
- sCol[1].iTable = pTabList->a[0].iCursor;
+ /* Initialize sCol[0..1] to be an expression parse tree for a
+ ** single column of an index. The sCol[0] node will be the TK_COLLATE
+ ** operator and sCol[1] will be the TK_COLUMN operator. Code below
+ ** will populate the specific collation and column number values
+ ** prior to comparing against the conflict-target expression.
+ */
+ memset(sCol, 0, sizeof(sCol));
+ sCol[0].op = TK_COLLATE;
+ sCol[0].pLeft = &sCol[1];
+ sCol[1].op = TK_COLUMN;
+ sCol[1].iTable = pTabList->a[0].iCursor;
- /* Check for matches against other indexes */
- for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
- int ii, jj, nn;
- if( !IsUniqueIndex(pIdx) ) continue;
- if( pTarget->nExpr!=pIdx->nKeyCol ) continue;
- if( pIdx->pPartIdxWhere ){
- if( pUpsert->pUpsertTargetWhere==0 ) continue;
- if( sqlcipher_sqlite3ExprCompare(pParse, pUpsert->pUpsertTargetWhere,
- pIdx->pPartIdxWhere, iCursor)!=0 ){
- continue;
+ /* Check for matches against other indexes */
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+ int ii, jj, nn;
+ if( !IsUniqueIndex(pIdx) ) continue;
+ if( pTarget->nExpr!=pIdx->nKeyCol ) continue;
+ if( pIdx->pPartIdxWhere ){
+ if( pUpsert->pUpsertTargetWhere==0 ) continue;
+ if( sqlcipher_sqlite3ExprCompare(pParse, pUpsert->pUpsertTargetWhere,
+ pIdx->pPartIdxWhere, iCursor)!=0 ){
+ continue;
+ }
}
- }
- nn = pIdx->nKeyCol;
- for(ii=0; ii<nn; ii++){
- Expr *pExpr;
- sCol[0].u.zToken = (char*)pIdx->azColl[ii];
- if( pIdx->aiColumn[ii]==XN_EXPR ){
- assert( pIdx->aColExpr!=0 );
- assert( pIdx->aColExpr->nExpr>ii );
- pExpr = pIdx->aColExpr->a[ii].pExpr;
- if( pExpr->op!=TK_COLLATE ){
- sCol[0].pLeft = pExpr;
+ nn = pIdx->nKeyCol;
+ for(ii=0; ii<nn; ii++){
+ Expr *pExpr;
+ sCol[0].u.zToken = (char*)pIdx->azColl[ii];
+ if( pIdx->aiColumn[ii]==XN_EXPR ){
+ assert( pIdx->aColExpr!=0 );
+ assert( pIdx->aColExpr->nExpr>ii );
+ pExpr = pIdx->aColExpr->a[ii].pExpr;
+ if( pExpr->op!=TK_COLLATE ){
+ sCol[0].pLeft = pExpr;
+ pExpr = &sCol[0];
+ }
+ }else{
+ sCol[0].pLeft = &sCol[1];
+ sCol[1].iColumn = pIdx->aiColumn[ii];
pExpr = &sCol[0];
}
- }else{
- sCol[0].pLeft = &sCol[1];
- sCol[1].iColumn = pIdx->aiColumn[ii];
- pExpr = &sCol[0];
- }
- for(jj=0; jj<nn; jj++){
- if( sqlcipher_sqlite3ExprCompare(pParse, pTarget->a[jj].pExpr, pExpr,iCursor)<2 ){
- break; /* Column ii of the index matches column jj of target */
+ for(jj=0; jj<nn; jj++){
+ if( sqlcipher_sqlite3ExprCompare(pParse,pTarget->a[jj].pExpr,pExpr,iCursor)<2 ){
+ break; /* Column ii of the index matches column jj of target */
+ }
+ }
+ if( jj>=nn ){
+ /* The target contains no match for column jj of the index */
+ break;
}
}
- if( jj>=nn ){
- /* The target contains no match for column jj of the index */
- break;
+ if( ii<nn ){
+ /* Column ii of the index did not match any term of the conflict target.
+ ** Continue the search with the next index. */
+ continue;
}
+ pUpsert->pUpsertIdx = pIdx;
+ break;
}
- if( ii<nn ){
- /* Column ii of the index did not match any term of the conflict target.
- ** Continue the search with the next index. */
- continue;
+ if( pUpsert->pUpsertIdx==0 ){
+ char zWhich[16];
+ if( nClause==0 && pUpsert->pNextUpsert==0 ){
+ zWhich[0] = 0;
+ }else{
+ sqlcipher_sqlite3_snprintf(sizeof(zWhich),zWhich,"%r ", nClause+1);
+ }
+ sqlcipher_sqlite3ErrorMsg(pParse, "%sON CONFLICT clause does not match any "
+ "PRIMARY KEY or UNIQUE constraint", zWhich);
+ return SQLITE_ERROR;
}
- pUpsert->pUpsertIdx = pIdx;
- return SQLITE_OK;
}
- sqlcipher_sqlite3ErrorMsg(pParse, "ON CONFLICT clause does not match any "
- "PRIMARY KEY or UNIQUE constraint");
- return SQLITE_ERROR;
+ return SQLITE_OK;
+}
+
+/*
+** Return true if pUpsert is the last ON CONFLICT clause with a
+** conflict target, or if pUpsert is followed by another ON CONFLICT
+** clause that targets the INTEGER PRIMARY KEY.
+*/
+SQLITE_PRIVATE int sqlcipher_sqlite3UpsertNextIsIPK(Upsert *pUpsert){
+ Upsert *pNext;
+ if( NEVER(pUpsert==0) ) return 0;
+ pNext = pUpsert->pNextUpsert;
+ if( pNext==0 ) return 1;
+ if( pNext->pUpsertTarget==0 ) return 1;
+ if( pNext->pUpsertIdx==0 ) return 1;
+ return 0;
+}
+
+/*
+** Given the list of ON CONFLICT clauses described by pUpsert, and
+** a particular index pIdx, return a pointer to the particular ON CONFLICT
+** clause that applies to the index. Or, if the index is not subject to
+** any ON CONFLICT clause, return NULL.
+*/
+SQLITE_PRIVATE Upsert *sqlcipher_sqlite3UpsertOfIndex(Upsert *pUpsert, Index *pIdx){
+ while(
+ pUpsert
+ && pUpsert->pUpsertTarget!=0
+ && pUpsert->pUpsertIdx!=pIdx
+ ){
+ pUpsert = pUpsert->pNextUpsert;
+ }
+ return pUpsert;
}
/*
@@ -144537,11 +152133,13 @@ SQLITE_PRIVATE void sqlcipher_sqlite3UpsertDoUpdate(
SrcList *pSrc; /* FROM clause for the UPDATE */
int iDataCur;
int i;
+ Upsert *pTop = pUpsert;
assert( v!=0 );
assert( pUpsert!=0 );
- VdbeNoopComment((v, "Begin DO UPDATE of UPSERT"));
iDataCur = pUpsert->iDataCur;
+ pUpsert = sqlcipher_sqlite3UpsertOfIndex(pTop, pIdx);
+ VdbeNoopComment((v, "Begin DO UPDATE of UPSERT"));
if( pIdx && iCur!=iDataCur ){
if( HasRowid(pTab) ){
int regRowid = sqlcipher_sqlite3GetTempReg(pParse);
@@ -144560,7 +152158,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3UpsertDoUpdate(
k = sqlcipher_sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[i]);
sqlcipher_sqlite3VdbeAddOp3(v, OP_Column, iCur, k, iPk+i);
VdbeComment((v, "%s.%s", pIdx->zName,
- pTab->aCol[pPk->aiColumn[i]].zName));
+ pTab->aCol[pPk->aiColumn[i]].zCnName));
}
sqlcipher_sqlite3VdbeVerifyAbortable(v, OE_Abort);
i = sqlcipher_sqlite3VdbeAddOp4Int(v, OP_Found, iDataCur, 0, iPk, nPk);
@@ -144571,19 +152169,17 @@ SQLITE_PRIVATE void sqlcipher_sqlite3UpsertDoUpdate(
sqlcipher_sqlite3VdbeJumpHere(v, i);
}
}
- /* pUpsert does not own pUpsertSrc - the outer INSERT statement does. So
- ** we have to make a copy before passing it down into sqlcipher_sqlite3Update() */
- pSrc = sqlcipher_sqlite3SrcListDup(db, pUpsert->pUpsertSrc, 0);
+ /* pUpsert does not own pTop->pUpsertSrc - the outer INSERT statement does.
+ ** So we have to make a copy before passing it down into sqlcipher_sqlite3Update() */
+ pSrc = sqlcipher_sqlite3SrcListDup(db, pTop->pUpsertSrc, 0);
/* excluded.* columns of type REAL need to be converted to a hard real */
for(i=0; i<pTab->nCol; i++){
if( pTab->aCol[i].affinity==SQLITE_AFF_REAL ){
- sqlcipher_sqlite3VdbeAddOp1(v, OP_RealAffinity, pUpsert->regData+i);
+ sqlcipher_sqlite3VdbeAddOp1(v, OP_RealAffinity, pTop->regData+i);
}
}
- sqlcipher_sqlite3Update(pParse, pSrc, pUpsert->pUpsertSet,
- pUpsert->pUpsertWhere, OE_Abort, 0, 0, pUpsert);
- pUpsert->pUpsertSet = 0; /* Will have been deleted by sqlcipher_sqlite3Update() */
- pUpsert->pUpsertWhere = 0; /* Will have been deleted by sqlcipher_sqlite3Update() */
+ sqlcipher_sqlite3Update(pParse, pSrc, sqlcipher_sqlite3ExprListDup(db,pUpsert->pUpsertSet,0),
+ sqlcipher_sqlite3ExprDup(db,pUpsert->pUpsertWhere,0), OE_Abort, 0, 0, pUpsert);
VdbeNoopComment((v, "End DO UPDATE of UPSERT"));
}
@@ -144744,8 +152340,8 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlcipher_sqlite3RunVacuum(
Btree *pTemp; /* The temporary database we vacuum into */
u32 saved_mDbFlags; /* Saved value of db->mDbFlags */
u64 saved_flags; /* Saved value of db->flags */
- int saved_nChange; /* Saved value of db->nChange */
- int saved_nTotalChange; /* Saved value of db->nTotalChange */
+ i64 saved_nChange; /* Saved value of db->nChange */
+ i64 saved_nTotalChange; /* Saved value of db->nTotalChange */
u32 saved_openFlags; /* Saved value of db->openFlags */
u8 saved_mTrace; /* Saved trace settings */
Db *pDb = 0; /* Database to detach at end of vacuum */
@@ -144832,10 +152428,10 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlcipher_sqlite3RunVacuum(
/* BEGIN SQLCIPHER */
#ifdef SQLITE_HAS_CODEC
if( db->nextPagesize ){
- extern void sqlcipher_sqlite3CodecGetKey(sqlcipher_sqlite3*, int, void**, int*);
+ extern void sqlcipherCodecGetKey(sqlcipher_sqlite3*, int, void**, int*);
int nKey;
char *zKey;
- sqlcipher_sqlite3CodecGetKey(db, iDb, (void**)&zKey, &nKey);
+ sqlcipherCodecGetKey(db, iDb, (void**)&zKey, &nKey);
if( nKey ) db->nextPagesize = 0;
}
#endif
@@ -144856,7 +152452,9 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlcipher_sqlite3RunVacuum(
/* Do not attempt to change the page size for a WAL database */
if( sqlcipher_sqlite3PagerGetJournalMode(sqlcipher_sqlite3BtreePager(pMain))
- ==PAGER_JOURNALMODE_WAL ){
+ ==PAGER_JOURNALMODE_WAL
+ && pOut==0
+ ){
db->nextPagesize = 0;
}
@@ -144972,6 +152570,7 @@ SQLITE_PRIVATE SQLITE_NOINLINE int sqlcipher_sqlite3RunVacuum(
assert( rc==SQLITE_OK );
if( pOut==0 ){
+ nRes = sqlcipher_sqlite3BtreeGetRequestedReserve(pTemp);
rc = sqlcipher_sqlite3BtreeSetPageSize(pMain, sqlcipher_sqlite3BtreeGetPageSize(pTemp), nRes,1);
}
@@ -145205,7 +152804,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3VtabLock(VTable *pVTab){
SQLITE_PRIVATE VTable *sqlcipher_sqlite3GetVTable(sqlcipher_sqlite3 *db, Table *pTab){
VTable *pVtab;
assert( IsVirtual(pTab) );
- for(pVtab=pTab->pVTable; pVtab && pVtab->db!=db; pVtab=pVtab->pNext);
+ for(pVtab=pTab->u.vtab.p; pVtab && pVtab->db!=db; pVtab=pVtab->pNext);
return pVtab;
}
@@ -145218,7 +152817,8 @@ SQLITE_PRIVATE void sqlcipher_sqlite3VtabUnlock(VTable *pVTab){
assert( db );
assert( pVTab->nRef>0 );
- assert( db->magic==SQLITE_MAGIC_OPEN || db->magic==SQLITE_MAGIC_ZOMBIE );
+ assert( db->eOpenState==SQLITE_STATE_OPEN
+ || db->eOpenState==SQLITE_STATE_ZOMBIE );
pVTab->nRef--;
if( pVTab->nRef==0 ){
@@ -145233,21 +152833,24 @@ SQLITE_PRIVATE void sqlcipher_sqlite3VtabUnlock(VTable *pVTab){
/*
** Table p is a virtual table. This function moves all elements in the
-** p->pVTable list to the sqlcipher_sqlite3.pDisconnect lists of their associated
+** p->u.vtab.p list to the sqlcipher_sqlite3.pDisconnect lists of their associated
** database connections to be disconnected at the next opportunity.
** Except, if argument db is not NULL, then the entry associated with
-** connection db is left in the p->pVTable list.
+** connection db is left in the p->u.vtab.p list.
*/
static VTable *vtabDisconnectAll(sqlcipher_sqlite3 *db, Table *p){
VTable *pRet = 0;
- VTable *pVTable = p->pVTable;
- p->pVTable = 0;
+ VTable *pVTable;
+
+ assert( IsVirtual(p) );
+ pVTable = p->u.vtab.p;
+ p->u.vtab.p = 0;
/* Assert that the mutex (if any) associated with the BtShared database
** that contains table p is held by the caller. See header comments
** above function sqlcipher_sqlite3VtabUnlockList() for an explanation of why
** this makes it safe to access the sqlcipher_sqlite3.pDisconnect list of any
- ** database connection that may have an entry in the p->pVTable list.
+ ** database connection that may have an entry in the p->u.vtab.p list.
*/
assert( db==0 || sqlcipher_sqlite3SchemaMutexHeld(db, 0, p->pSchema) );
@@ -145257,7 +152860,7 @@ static VTable *vtabDisconnectAll(sqlcipher_sqlite3 *db, Table *p){
assert( db2 );
if( db2==db ){
pRet = pVTable;
- p->pVTable = pRet;
+ p->u.vtab.p = pRet;
pRet->pNext = 0;
}else{
pVTable->pNext = db2->pDisconnect;
@@ -145285,7 +152888,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3VtabDisconnect(sqlcipher_sqlite3 *db, Table
assert( sqlcipher_sqlite3BtreeHoldsAllMutexes(db) );
assert( sqlcipher_sqlite3_mutex_held(db->mutex) );
- for(ppVTab=&p->pVTable; *ppVTab; ppVTab=&(*ppVTab)->pNext){
+ for(ppVTab=&p->u.vtab.p; *ppVTab; ppVTab=&(*ppVTab)->pNext){
if( (*ppVTab)->db==db ){
VTable *pVTab = *ppVTab;
*ppVTab = pVTab->pNext;
@@ -145348,37 +152951,41 @@ SQLITE_PRIVATE void sqlcipher_sqlite3VtabUnlockList(sqlcipher_sqlite3 *db){
** database connection.
*/
SQLITE_PRIVATE void sqlcipher_sqlite3VtabClear(sqlcipher_sqlite3 *db, Table *p){
+ assert( IsVirtual(p) );
if( !db || db->pnBytesFreed==0 ) vtabDisconnectAll(0, p);
- if( p->azModuleArg ){
+ if( p->u.vtab.azArg ){
int i;
- for(i=0; i<p->nModuleArg; i++){
- if( i!=1 ) sqlcipher_sqlite3DbFree(db, p->azModuleArg[i]);
+ for(i=0; i<p->u.vtab.nArg; i++){
+ if( i!=1 ) sqlcipher_sqlite3DbFree(db, p->u.vtab.azArg[i]);
}
- sqlcipher_sqlite3DbFree(db, p->azModuleArg);
+ sqlcipher_sqlite3DbFree(db, p->u.vtab.azArg);
}
}
/*
-** Add a new module argument to pTable->azModuleArg[].
+** Add a new module argument to pTable->u.vtab.azArg[].
** The string is not copied - the pointer is stored. The
** string will be freed automatically when the table is
** deleted.
*/
static void addModuleArgument(Parse *pParse, Table *pTable, char *zArg){
- sqlcipher_sqlite3_int64 nBytes = sizeof(char *)*(2+pTable->nModuleArg);
+ sqlcipher_sqlite3_int64 nBytes;
char **azModuleArg;
sqlcipher_sqlite3 *db = pParse->db;
- if( pTable->nModuleArg+3>=db->aLimit[SQLITE_LIMIT_COLUMN] ){
+
+ assert( IsVirtual(pTable) );
+ nBytes = sizeof(char *)*(2+pTable->u.vtab.nArg);
+ if( pTable->u.vtab.nArg+3>=db->aLimit[SQLITE_LIMIT_COLUMN] ){
sqlcipher_sqlite3ErrorMsg(pParse, "too many columns on %s", pTable->zName);
}
- azModuleArg = sqlcipher_sqlite3DbRealloc(db, pTable->azModuleArg, nBytes);
+ azModuleArg = sqlcipher_sqlite3DbRealloc(db, pTable->u.vtab.azArg, nBytes);
if( azModuleArg==0 ){
sqlcipher_sqlite3DbFree(db, zArg);
}else{
- int i = pTable->nModuleArg++;
+ int i = pTable->u.vtab.nArg++;
azModuleArg[i] = zArg;
azModuleArg[i+1] = 0;
- pTable->azModuleArg = azModuleArg;
+ pTable->u.vtab.azArg = azModuleArg;
}
}
@@ -145401,10 +153008,11 @@ SQLITE_PRIVATE void sqlcipher_sqlite3VtabBeginParse(
pTable = pParse->pNewTable;
if( pTable==0 ) return;
assert( 0==pTable->pIndex );
+ pTable->eTabType = TABTYP_VTAB;
db = pParse->db;
- assert( pTable->nModuleArg==0 );
+ assert( pTable->u.vtab.nArg==0 );
addModuleArgument(pParse, pTable, sqlcipher_sqlite3NameFromToken(db, pModuleName));
addModuleArgument(pParse, pTable, 0);
addModuleArgument(pParse, pTable, sqlcipher_sqlite3DbStrDup(db, pTable->zName));
@@ -145421,11 +153029,11 @@ SQLITE_PRIVATE void sqlcipher_sqlite3VtabBeginParse(
** sqlite_schema table, has already been made by sqlcipher_sqlite3StartTable().
** The second call, to obtain permission to create the table, is made now.
*/
- if( pTable->azModuleArg ){
+ if( pTable->u.vtab.azArg ){
int iDb = sqlcipher_sqlite3SchemaToIndex(db, pTable->pSchema);
assert( iDb>=0 ); /* The database the table is being created in */
sqlcipher_sqlite3AuthCheck(pParse, SQLITE_CREATE_VTABLE, pTable->zName,
- pTable->azModuleArg[0], pParse->db->aDb[iDb].zDbSName);
+ pTable->u.vtab.azArg[0], pParse->db->aDb[iDb].zDbSName);
}
#endif
}
@@ -145453,9 +153061,10 @@ SQLITE_PRIVATE void sqlcipher_sqlite3VtabFinishParse(Parse *pParse, Token *pEnd)
sqlcipher_sqlite3 *db = pParse->db; /* The database connection */
if( pTab==0 ) return;
+ assert( IsVirtual(pTab) );
addArgumentToVtab(pParse);
pParse->sArg.z = 0;
- if( pTab->nModuleArg<1 ) return;
+ if( pTab->u.vtab.nArg<1 ) return;
/* If the CREATE VIRTUAL TABLE statement is being entered for the
** first time (in other words if the virtual table is actually being
@@ -145488,7 +153097,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3VtabFinishParse(Parse *pParse, Token *pEnd)
*/
iDb = sqlcipher_sqlite3SchemaToIndex(db, pTab->pSchema);
sqlcipher_sqlite3NestedParse(pParse,
- "UPDATE %Q." DFLT_SCHEMA_TABLE " "
+ "UPDATE %Q." LEGACY_SCHEMA_TABLE " "
"SET type='table', name=%Q, tbl_name=%Q, rootpage=0, sql=%Q "
"WHERE rowid=#%d",
db->aDb[iDb].zDbSName,
@@ -145502,24 +153111,20 @@ SQLITE_PRIVATE void sqlcipher_sqlite3VtabFinishParse(Parse *pParse, Token *pEnd)
sqlcipher_sqlite3VdbeAddOp0(v, OP_Expire);
zWhere = sqlcipher_sqlite3MPrintf(db, "name=%Q AND sql=%Q", pTab->zName, zStmt);
- sqlcipher_sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere);
+ sqlcipher_sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere, 0);
sqlcipher_sqlite3DbFree(db, zStmt);
iReg = ++pParse->nMem;
sqlcipher_sqlite3VdbeLoadString(v, iReg, pTab->zName);
sqlcipher_sqlite3VdbeAddOp2(v, OP_VCreate, iDb, iReg);
- }
-
- /* If we are rereading the sqlite_schema table create the in-memory
- ** record of the table. The xConnect() method is not called until
- ** the first time the virtual table is used in an SQL statement. This
- ** allows a schema that contains virtual tables to be loaded before
- ** the required virtual table implementations are registered. */
- else {
+ }else{
+ /* If we are rereading the sqlite_schema table create the in-memory
+ ** record of the table. */
Table *pOld;
Schema *pSchema = pTab->pSchema;
const char *zName = pTab->zName;
- assert( sqlcipher_sqlite3SchemaMutexHeld(db, 0, pSchema) );
+ assert( zName!=0 );
+ sqlcipher_sqlite3MarkAllShadowTablesOf(db, pTab);
pOld = sqlcipher_sqlite3HashInsert(&pSchema->tblHash, zName, pTab);
if( pOld ){
sqlcipher_sqlite3OomFault(db);
@@ -145570,13 +153175,16 @@ static int vtabCallConstructor(
VtabCtx sCtx;
VTable *pVTable;
int rc;
- const char *const*azArg = (const char *const*)pTab->azModuleArg;
- int nArg = pTab->nModuleArg;
+ const char *const*azArg;
+ int nArg = pTab->u.vtab.nArg;
char *zErr = 0;
char *zModuleName;
int iDb;
VtabCtx *pCtx;
+ assert( IsVirtual(pTab) );
+ azArg = (const char *const*)pTab->u.vtab.azArg;
+
/* Check that the virtual-table is not already being initialized */
for(pCtx=db->pVtabCtx; pCtx; pCtx=pCtx->pPrior){
if( pCtx->pTab==pTab ){
@@ -145603,7 +153211,7 @@ static int vtabCallConstructor(
pVTable->eVtabRisk = SQLITE_VTABRISK_Normal;
iDb = sqlcipher_sqlite3SchemaToIndex(db, pTab->pSchema);
- pTab->azModuleArg[1] = db->aDb[iDb].zDbSName;
+ pTab->u.vtab.azArg[1] = db->aDb[iDb].zDbSName;
/* Invoke the virtual table constructor */
assert( &db->pVtabCtx );
@@ -145642,12 +153250,12 @@ static int vtabCallConstructor(
int iCol;
u16 oooHidden = 0;
/* If everything went according to plan, link the new VTable structure
- ** into the linked list headed by pTab->pVTable. Then loop through the
+ ** into the linked list headed by pTab->u.vtab.p. Then loop through the
** columns of the table to see if any of them contain the token "hidden".
** If so, set the Column COLFLAG_HIDDEN flag and remove the token from
** the type string. */
- pVTable->pNext = pTab->pVTable;
- pTab->pVTable = pVTable;
+ pVTable->pNext = pTab->u.vtab.p;
+ pTab->u.vtab.p = pVTable;
for(iCol=0; iCol<pTab->nCol; iCol++){
char *zType = sqlcipher_sqlite3ColumnType(&pTab->aCol[iCol], "");
@@ -145673,6 +153281,7 @@ static int vtabCallConstructor(
zType[i-1] = '\0';
}
pTab->aCol[iCol].colFlags |= COLFLAG_HIDDEN;
+ pTab->tabFlags |= TF_HasHidden;
oooHidden = TF_OOOHidden;
}else{
pTab->tabFlags |= oooHidden;
@@ -145699,16 +153308,17 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VtabCallConnect(Parse *pParse, Table *pTab){
int rc;
assert( pTab );
- if( !IsVirtual(pTab) || sqlcipher_sqlite3GetVTable(db, pTab) ){
+ assert( IsVirtual(pTab) );
+ if( sqlcipher_sqlite3GetVTable(db, pTab) ){
return SQLITE_OK;
}
/* Locate the required virtual table module */
- zMod = pTab->azModuleArg[0];
+ zMod = pTab->u.vtab.azArg[0];
pMod = (Module*)sqlcipher_sqlite3HashFind(&db->aModule, zMod);
if( !pMod ){
- const char *zModule = pTab->azModuleArg[0];
+ const char *zModule = pTab->u.vtab.azArg[0];
sqlcipher_sqlite3ErrorMsg(pParse, "no such module: %s", zModule);
rc = SQLITE_ERROR;
}else{
@@ -145771,10 +153381,10 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VtabCallCreate(sqlcipher_sqlite3 *db, int iD
const char *zMod;
pTab = sqlcipher_sqlite3FindTable(db, zTab, db->aDb[iDb].zDbSName);
- assert( pTab && IsVirtual(pTab) && !pTab->pVTable );
+ assert( pTab && IsVirtual(pTab) && !pTab->u.vtab.p );
/* Locate the required virtual table module */
- zMod = pTab->azModuleArg[0];
+ zMod = pTab->u.vtab.azArg[0];
pMod = (Module*)sqlcipher_sqlite3HashFind(&db->aModule, zMod);
/* If the module has been registered and includes a Create method,
@@ -145809,8 +153419,8 @@ SQLITE_API int sqlcipher_sqlite3_declare_vtab(sqlcipher_sqlite3 *db, const char
VtabCtx *pCtx;
int rc = SQLITE_OK;
Table *pTab;
- char *zErr = 0;
Parse sParse;
+ int initBusy;
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlcipher_sqlite3SafetyCheckOk(db) || zCreateTable==0 ){
@@ -145827,21 +153437,28 @@ SQLITE_API int sqlcipher_sqlite3_declare_vtab(sqlcipher_sqlite3 *db, const char
pTab = pCtx->pTab;
assert( IsVirtual(pTab) );
- memset(&sParse, 0, sizeof(sParse));
+ sqlcipher_sqlite3ParseObjectInit(&sParse, db);
sParse.eParseMode = PARSE_MODE_DECLARE_VTAB;
- sParse.db = db;
+ sParse.disableTriggers = 1;
+ /* We should never be able to reach this point while loading the
+ ** schema. Nevertheless, defend against that (turn off db->init.busy)
+ ** in case a bug arises. */
+ assert( db->init.busy==0 );
+ initBusy = db->init.busy;
+ db->init.busy = 0;
sParse.nQueryLoop = 1;
- if( SQLITE_OK==sqlcipher_sqlite3RunParser(&sParse, zCreateTable, &zErr)
- && sParse.pNewTable
- && !db->mallocFailed
- && !sParse.pNewTable->pSelect
- && !IsVirtual(sParse.pNewTable)
+ if( SQLITE_OK==sqlcipher_sqlite3RunParser(&sParse, zCreateTable)
+ && ALWAYS(sParse.pNewTable!=0)
+ && ALWAYS(!db->mallocFailed)
+ && IsOrdinaryTable(sParse.pNewTable)
){
+ assert( sParse.zErrMsg==0 );
if( !pTab->aCol ){
Table *pNew = sParse.pNewTable;
Index *pIdx;
pTab->aCol = pNew->aCol;
- pTab->nCol = pNew->nCol;
+ sqlcipher_sqlite3ExprListDelete(db, pNew->u.tab.pDfltList);
+ pTab->nNVCol = pTab->nCol = pNew->nCol;
pTab->tabFlags |= pNew->tabFlags & (TF_WithoutRowid|TF_NoVisibleRowid);
pNew->nCol = 0;
pNew->aCol = 0;
@@ -145865,8 +153482,9 @@ SQLITE_API int sqlcipher_sqlite3_declare_vtab(sqlcipher_sqlite3 *db, const char
}
pCtx->bDeclared = 1;
}else{
- sqlcipher_sqlite3ErrorWithMsg(db, SQLITE_ERROR, (zErr ? "%s" : 0), zErr);
- sqlcipher_sqlite3DbFree(db, zErr);
+ sqlcipher_sqlite3ErrorWithMsg(db, SQLITE_ERROR,
+ (sParse.zErrMsg ? "%s" : 0), sParse.zErrMsg);
+ sqlcipher_sqlite3DbFree(db, sParse.zErrMsg);
rc = SQLITE_ERROR;
}
sParse.eParseMode = PARSE_MODE_NORMAL;
@@ -145875,7 +153493,8 @@ SQLITE_API int sqlcipher_sqlite3_declare_vtab(sqlcipher_sqlite3 *db, const char
sqlcipher_sqlite3VdbeFinalize(sParse.pVdbe);
}
sqlcipher_sqlite3DeleteTable(db, sParse.pNewTable);
- sqlcipher_sqlite3ParserReset(&sParse);
+ sqlcipher_sqlite3ParseObjectReset(&sParse);
+ db->init.busy = initBusy;
assert( (rc&0xff)==rc );
rc = sqlcipher_sqlite3ApiExit(db, rc);
@@ -145895,10 +153514,13 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VtabCallDestroy(sqlcipher_sqlite3 *db, int i
Table *pTab;
pTab = sqlcipher_sqlite3FindTable(db, zTab, db->aDb[iDb].zDbSName);
- if( pTab!=0 && ALWAYS(pTab->pVTable!=0) ){
+ if( ALWAYS(pTab!=0)
+ && ALWAYS(IsVirtual(pTab))
+ && ALWAYS(pTab->u.vtab.p!=0)
+ ){
VTable *p;
int (*xDestroy)(sqlcipher_sqlite3_vtab *);
- for(p=pTab->pVTable; p; p=p->pNext){
+ for(p=pTab->u.vtab.p; p; p=p->pNext){
assert( p->pVtab );
if( p->pVtab->nRef>0 ){
return SQLITE_LOCKED;
@@ -145912,9 +153534,9 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VtabCallDestroy(sqlcipher_sqlite3 *db, int i
rc = xDestroy(p->pVtab);
/* Remove the sqlcipher_sqlite3_vtab* from the aVTrans[] array, if applicable */
if( rc==SQLITE_OK ){
- assert( pTab->pVTable==p && p->pNext==0 );
+ assert( pTab->u.vtab.p==p && p->pNext==0 );
p->pVtab = 0;
- pTab->pVTable = 0;
+ pTab->u.vtab.p = 0;
sqlcipher_sqlite3VtabUnlock(p);
}
sqlcipher_sqlite3DeleteTable(db, pTab);
@@ -146128,6 +153750,7 @@ SQLITE_PRIVATE FuncDef *sqlcipher_sqlite3VtabOverloadFunction(
/* Check to see the left operand is a column in a virtual table */
if( NEVER(pExpr==0) ) return pDef;
if( pExpr->op!=TK_COLUMN ) return pDef;
+ assert( ExprUseYTab(pExpr) );
pTab = pExpr->y.pTab;
if( pTab==0 ) return pDef;
if( !IsVirtual(pTab) ) return pDef;
@@ -146202,8 +153825,9 @@ SQLITE_PRIVATE void sqlcipher_sqlite3VtabMakeWritable(Parse *pParse, Table *pTab
/*
** Check to see if virtual table module pMod can be have an eponymous
** virtual table instance. If it can, create one if one does not already
-** exist. Return non-zero if the eponymous virtual table instance exists
-** when this routine returns, and return zero if it does not exist.
+** exist. Return non-zero if either the eponymous virtual table instance
+** exists when this routine returns or if an attempt to create it failed
+** and an error message was left in pParse.
**
** An eponymous virtual table instance is one that is named after its
** module, and more importantly, does not require a CREATE VIRTUAL TABLE
@@ -146230,9 +153854,11 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VtabEponymousTableInit(Parse *pParse, Module
}
pMod->pEpoTab = pTab;
pTab->nTabRef = 1;
+ pTab->eTabType = TABTYP_VTAB;
pTab->pSchema = db->aDb[0].pSchema;
- assert( pTab->nModuleArg==0 );
+ assert( pTab->u.vtab.nArg==0 );
pTab->iPKey = -1;
+ pTab->tabFlags |= TF_Eponymous;
addModuleArgument(pParse, pTab, sqlcipher_sqlite3DbStrDup(db, pTab->zName));
addModuleArgument(pParse, pTab, 0);
addModuleArgument(pParse, pTab, sqlcipher_sqlite3DbStrDup(db, pTab->zName));
@@ -146241,7 +153867,6 @@ SQLITE_PRIVATE int sqlcipher_sqlite3VtabEponymousTableInit(Parse *pParse, Module
sqlcipher_sqlite3ErrorMsg(pParse, "%s", zErr);
sqlcipher_sqlite3DbFree(db, zErr);
sqlcipher_sqlite3VtabEponymousTableClear(db, pMod);
- return 0;
}
return 1;
}
@@ -146373,19 +153998,6 @@ SQLITE_API int sqlcipher_sqlite3_vtab_config(sqlcipher_sqlite3 *db, int op, ...)
#ifndef SQLITE_WHEREINT_H
#define SQLITE_WHEREINT_H
-/*
-** Trace output macros
-*/
-#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
-/***/ extern int sqlcipher_sqlite3WhereTrace;
-#endif
-#if defined(SQLITE_DEBUG) \
- && (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHERETRACE))
-# define WHERETRACE(K,X) if(sqlcipher_sqlite3WhereTrace&(K)) sqlcipher_sqlite3DebugPrintf X
-# define WHERETRACE_ENABLED 1
-#else
-# define WHERETRACE(K,X)
-#endif
/* Forward references
*/
@@ -146401,6 +154013,28 @@ typedef struct WhereLoopBuilder WhereLoopBuilder;
typedef struct WhereScan WhereScan;
typedef struct WhereOrCost WhereOrCost;
typedef struct WhereOrSet WhereOrSet;
+typedef struct WhereMemBlock WhereMemBlock;
+typedef struct WhereRightJoin WhereRightJoin;
+
+/*
+** This object is a header on a block of allocated memory that will be
+** automatically freed when its WInfo oject is destructed.
+*/
+struct WhereMemBlock {
+ WhereMemBlock *pNext; /* Next block in the chain */
+ u64 sz; /* Bytes of space */
+};
+
+/*
+** Extra information attached to a WhereLevel that is a RIGHT JOIN.
+*/
+struct WhereRightJoin {
+ int iMatch; /* Cursor used to determine prior matched rows */
+ int regBloom; /* Bloom filter for iRJMatch */
+ int regReturn; /* Return register for the interior subroutine */
+ int addrSubrtn; /* Starting address for the interior subroutine */
+ int endSubrtn; /* The last opcode in the interior subroutine */
+};
/*
** This object contains information needed to implement a single nested
@@ -146433,6 +154067,8 @@ struct WhereLevel {
u32 iLikeRepCntr; /* LIKE range processing counter register (times 2) */
int addrLikeRep; /* LIKE range processing address */
#endif
+ int regFilter; /* Bloom filter */
+ WhereRightJoin *pRJ; /* Extra information for RIGHT JOIN */
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 end the loop */
@@ -146447,7 +154083,7 @@ struct WhereLevel {
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 */
+ Index *pCoveringIdx; /* Possible covering index for WHERE_MULTI_OR */
} u;
struct WhereLoop *pWLoop; /* The selected WhereLoop object */
Bitmask notReady; /* FROM entries not usable at this level */
@@ -146491,10 +154127,12 @@ struct WhereLoop {
} btree;
struct { /* Information for virtual tables */
int idxNum; /* Index number */
- u8 needFree; /* True if sqlcipher_sqlite3_free(idxStr) is needed */
+ u32 needFree : 1; /* True if sqlcipher_sqlite3_free(idxStr) is needed */
+ u32 bOmitOffset : 1; /* True to let virtual table handle offset */
i8 isOrdered; /* True if satisfies ORDER BY */
u16 omitMask; /* Terms that may be omitted */
char *idxStr; /* Index identifier string */
+ u32 mHandleIn; /* Terms to handle as IN(...) instead of == */
} vtab;
} u;
u32 wsFlags; /* WHERE_* flags describing the plan */
@@ -146638,12 +154276,8 @@ struct WhereTerm {
#define TERM_COPIED 0x0008 /* Has a child */
#define TERM_ORINFO 0x0010 /* Need to free the WhereTerm.u.pOrInfo object */
#define TERM_ANDINFO 0x0020 /* Need to free the WhereTerm.u.pAndInfo obj */
-#define TERM_OR_OK 0x0040 /* Used during OR-clause processing */
-#ifdef SQLITE_ENABLE_STAT4
-# define TERM_VNULL 0x0080 /* Manufactured x>NULL or x<=NULL term */
-#else
-# define TERM_VNULL 0x0000 /* Disabled if not using stat4 */
-#endif
+#define TERM_OK 0x0040 /* Used during OR-clause processing */
+#define TERM_VNULL 0x0080 /* Manufactured x>NULL or x<=NULL term */
#define TERM_LIKEOPT 0x0100 /* Virtual terms from the LIKE optimization */
#define TERM_LIKECOND 0x0200 /* Conditionally this LIKE operator term */
#define TERM_LIKE 0x0400 /* The original LIKE operator */
@@ -146655,6 +154289,7 @@ struct WhereTerm {
#else
# define TERM_HIGHTRUTH 0 /* Only used with STAT4 */
#endif
+#define TERM_SLICE 0x8000 /* One slice of a row-value/vector comparison */
/*
** An instance of the WhereScan object is used as an iterator for locating
@@ -146665,11 +154300,11 @@ struct WhereScan {
WhereClause *pWC; /* WhereClause currently being scanned */
const char *zCollName; /* Required collating sequence, if not NULL */
Expr *pIdxExpr; /* Search for this index expression */
- 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] */
+ u32 opMask; /* Acceptable operators */
+ char idxaff; /* Must match this affinity, if zCollName!=NULL */
+ unsigned char iEquiv; /* Current slot in aiCur[] and aiColumn[] */
+ unsigned char nEquiv; /* Number of entries in aiCur[] and aiColumn[] */
int aiCur[11]; /* Cursors in the equivalence class */
i16 aiColumn[11]; /* Corresponding column number in the eq-class */
};
@@ -146693,6 +154328,7 @@ struct WhereClause {
u8 hasOr; /* True if any a[].eOperator is WO_OR */
int nTerm; /* Number of terms */
int nSlot; /* Number of entries in a[] */
+ int nBase; /* Number of terms through the last non-Virtual */
WhereTerm *a; /* Each a[] describes a term of the WHERE cluase */
#if defined(SQLITE_SMALL_STACK)
WhereTerm aStatic[1]; /* Initial static space for a[] */
@@ -146751,18 +154387,12 @@ struct WhereMaskSet {
};
/*
-** Initialize a WhereMaskSet object
-*/
-#define initMaskSet(P) (P)->n=0
-
-/*
** This object is a convenience wrapper holding all information needed
** to construct WhereLoop objects for a particular query.
*/
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_STAT4
@@ -146830,6 +154460,9 @@ struct WhereInfo {
ExprList *pOrderBy; /* The ORDER BY clause or NULL */
ExprList *pResultSet; /* Result set of the query */
Expr *pWhere; /* The complete WHERE clause */
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ Select *pLimit; /* Used to access LIMIT expr/registers for vtabs */
+#endif
int aiCurOnePass[2]; /* OP_OpenWrite cursors for the ONEPASS opt */
int iContinue; /* Jump here to continue with next record */
int iBreak; /* Jump here to break out of the loop */
@@ -146849,6 +154482,7 @@ struct WhereInfo {
int iEndWhere; /* End of the WHERE clause itself */
WhereLoop *pLoops; /* List of all WhereLoop objects */
WhereExprMod *pExprMods; /* Expression modifications */
+ WhereMemBlock *pMemToFree;/* Memory to free when this object destroyed */
Bitmask revMask; /* Mask of ORDER BY terms that need reversing */
WhereClause sWC; /* Decomposition of the WHERE clause */
WhereMaskSet sMaskSet; /* Map cursor numbers to bitmasks */
@@ -146874,6 +154508,8 @@ SQLITE_PRIVATE WhereTerm *sqlcipher_sqlite3WhereFindTerm(
u32 op, /* Mask of WO_xx values describing operator */
Index *pIdx /* Must be compatible with this index, if not NULL */
);
+SQLITE_PRIVATE void *sqlcipher_sqlite3WhereMalloc(WhereInfo *pWInfo, u64 nByte);
+SQLITE_PRIVATE void *sqlcipher_sqlite3WhereRealloc(WhereInfo *pWInfo, void *pOld, u64 nByte);
/* wherecode.c: */
#ifndef SQLITE_OMIT_EXPLAIN
@@ -146883,8 +154519,14 @@ SQLITE_PRIVATE int sqlcipher_sqlite3WhereExplainOneScan(
WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */
u16 wctrlFlags /* Flags passed to sqlcipher_sqlite3WhereBegin() */
);
+SQLITE_PRIVATE int sqlcipher_sqlite3WhereExplainBloomFilter(
+ const Parse *pParse, /* Parse context */
+ const WhereInfo *pWInfo, /* WHERE clause */
+ const WhereLevel *pLevel /* Bloom filter on this level */
+);
#else
# define sqlcipher_sqlite3WhereExplainOneScan(u,v,w,x) 0
+# define sqlcipher_sqlite3WhereExplainBloomFilter(u,v,w) 0
#endif /* SQLITE_OMIT_EXPLAIN */
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
SQLITE_PRIVATE void sqlcipher_sqlite3WhereAddScanStatus(
@@ -146904,16 +154546,22 @@ SQLITE_PRIVATE Bitmask sqlcipher_sqlite3WhereCodeOneLoopStart(
WhereLevel *pLevel, /* The current level pointer */
Bitmask notReady /* Which tables are currently available */
);
+SQLITE_PRIVATE SQLITE_NOINLINE void sqlcipher_sqlite3WhereRightJoinLoop(
+ WhereInfo *pWInfo,
+ int iLevel,
+ WhereLevel *pLevel
+);
/* whereexpr.c: */
SQLITE_PRIVATE void sqlcipher_sqlite3WhereClauseInit(WhereClause*,WhereInfo*);
SQLITE_PRIVATE void sqlcipher_sqlite3WhereClauseClear(WhereClause*);
SQLITE_PRIVATE void sqlcipher_sqlite3WhereSplit(WhereClause*,Expr*,u8);
+SQLITE_PRIVATE void sqlcipher_sqlite3WhereAddLimit(WhereClause*, Select*);
SQLITE_PRIVATE Bitmask sqlcipher_sqlite3WhereExprUsage(WhereMaskSet*, Expr*);
SQLITE_PRIVATE Bitmask sqlcipher_sqlite3WhereExprUsageNN(WhereMaskSet*, Expr*);
SQLITE_PRIVATE Bitmask sqlcipher_sqlite3WhereExprListUsage(WhereMaskSet*, ExprList*);
SQLITE_PRIVATE void sqlcipher_sqlite3WhereExprAnalyze(SrcList*, WhereClause*);
-SQLITE_PRIVATE void sqlcipher_sqlite3WhereTabFuncArgs(Parse*, struct SrcList_item*, WhereClause*);
+SQLITE_PRIVATE void sqlcipher_sqlite3WhereTabFuncArgs(Parse*, SrcItem*, WhereClause*);
@@ -146945,8 +154593,9 @@ SQLITE_PRIVATE void sqlcipher_sqlite3WhereTabFuncArgs(Parse*, struct SrcList_ite
#define WO_AND 0x0400 /* Two or more AND-connected terms */
#define WO_EQUIV 0x0800 /* Of the form A==B, both columns */
#define WO_NOOP 0x1000 /* This term does not restrict search space */
+#define WO_ROWVAL 0x2000 /* A row-value term */
-#define WO_ALL 0x1fff /* Mask of all possible WO_* values */
+#define WO_ALL 0x3fff /* Mask of all possible WO_* values */
#define WO_SINGLE 0x01ff /* Mask of all non-compound WO_* values */
/*
@@ -146976,6 +154625,10 @@ SQLITE_PRIVATE void sqlcipher_sqlite3WhereTabFuncArgs(Parse*, struct SrcList_ite
#define WHERE_IN_EARLYOUT 0x00040000 /* Perhaps quit IN loops early */
#define WHERE_BIGNULL_SORT 0x00080000 /* Column nEq of index is BIGNULL */
#define WHERE_IN_SEEKSCAN 0x00100000 /* Seek-scan optimization for IN */
+#define WHERE_TRANSCONS 0x00200000 /* Uses a transitive constraint */
+#define WHERE_BLOOMFILTER 0x00400000 /* Consider using a Bloom-filter */
+#define WHERE_SELFCULL 0x00800000 /* nOut reduced by extra WHERE terms */
+#define WHERE_OMIT_OFFSET 0x01000000 /* Set offset counter to zero */
#endif /* !defined(SQLITE_WHEREINT_H) */
@@ -146991,7 +154644,7 @@ static const char *explainIndexColumnName(Index *pIdx, int i){
i = pIdx->aiColumn[i];
if( i==XN_EXPR ) return "<expr>";
if( i==XN_ROWID ) return "rowid";
- return pIdx->pTable->aCol[i].zName;
+ return pIdx->pTable->aCol[i].zCnName;
}
/*
@@ -147091,7 +154744,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3WhereExplainOneScan(
if( sqlcipher_sqlite3ParseToplevel(pParse)->explain==2 )
#endif
{
- struct SrcList_item *pItem = &pTabList->a[pLevel->iFrom];
+ SrcItem *pItem = &pTabList->a[pLevel->iFrom];
Vdbe *v = pParse->pVdbe; /* VM being constructed */
sqlcipher_sqlite3 *db = pParse->db; /* Database handle */
int isSearch; /* True for a SEARCH. False for SCAN. */
@@ -147110,16 +154763,8 @@ SQLITE_PRIVATE int sqlcipher_sqlite3WhereExplainOneScan(
|| (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX));
sqlcipher_sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH);
- sqlcipher_sqlite3_str_appendall(&str, isSearch ? "SEARCH" : "SCAN");
- if( pItem->pSelect ){
- sqlcipher_sqlite3_str_appendf(&str, " SUBQUERY %u", pItem->pSelect->selId);
- }else{
- sqlcipher_sqlite3_str_appendf(&str, " TABLE %s", pItem->zName);
- }
-
- if( pItem->zAlias ){
- sqlcipher_sqlite3_str_appendf(&str, " AS %s", pItem->zAlias);
- }
+ str.printfFlags = SQLITE_PRINTF_INTERNAL;
+ sqlcipher_sqlite3_str_appendf(&str, "%s %S", isSearch ? "SEARCH" : "SCAN", pItem);
if( (flags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0 ){
const char *zFmt = 0;
Index *pIdx;
@@ -147146,19 +154791,27 @@ SQLITE_PRIVATE int sqlcipher_sqlite3WhereExplainOneScan(
explainIndexRange(&str, pLoop);
}
}else if( (flags & WHERE_IPK)!=0 && (flags & WHERE_CONSTRAINT)!=0 ){
- const char *zRangeOp;
+ char cRangeOp;
+#if 0 /* Better output, but breaks many tests */
+ const Table *pTab = pItem->pTab;
+ const char *zRowid = pTab->iPKey>=0 ? pTab->aCol[pTab->iPKey].zCnName:
+ "rowid";
+#else
+ const char *zRowid = "rowid";
+#endif
+ sqlcipher_sqlite3_str_appendf(&str, " USING INTEGER PRIMARY KEY (%s", zRowid);
if( flags&(WHERE_COLUMN_EQ|WHERE_COLUMN_IN) ){
- zRangeOp = "=";
+ cRangeOp = '=';
}else if( (flags&WHERE_BOTH_LIMIT)==WHERE_BOTH_LIMIT ){
- zRangeOp = ">? AND rowid<";
+ sqlcipher_sqlite3_str_appendf(&str, ">? AND %s", zRowid);
+ cRangeOp = '<';
}else if( flags&WHERE_BTM_LIMIT ){
- zRangeOp = ">";
+ cRangeOp = '>';
}else{
assert( flags&WHERE_TOP_LIMIT);
- zRangeOp = "<";
+ cRangeOp = '<';
}
- sqlcipher_sqlite3_str_appendf(&str,
- " USING INTEGER PRIMARY KEY (rowid%s?)",zRangeOp);
+ sqlcipher_sqlite3_str_appendf(&str, "%c?)", cRangeOp);
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
else if( (flags & WHERE_VIRTUALTABLE)!=0 ){
@@ -147166,6 +154819,9 @@ SQLITE_PRIVATE int sqlcipher_sqlite3WhereExplainOneScan(
pLoop->u.vtab.idxNum, pLoop->u.vtab.idxStr);
}
#endif
+ if( pItem->fg.jointype & JT_LEFT ){
+ sqlcipher_sqlite3_str_appendf(&str, " LEFT-JOIN");
+ }
#ifdef SQLITE_EXPLAIN_ESTIMATED_ROWS
if( pLoop->nOut>=10 ){
sqlcipher_sqlite3_str_appendf(&str, " (~%llu rows)",
@@ -147181,6 +154837,56 @@ SQLITE_PRIVATE int sqlcipher_sqlite3WhereExplainOneScan(
}
return ret;
}
+
+/*
+** Add a single OP_Explain opcode that describes a Bloom filter.
+**
+** Or if not processing EXPLAIN QUERY PLAN and not in a SQLITE_DEBUG and/or
+** SQLITE_ENABLE_STMT_SCANSTATUS build, then OP_Explain opcodes are not
+** required and this routine is a no-op.
+**
+** If an OP_Explain opcode is added to the VM, its address is returned.
+** Otherwise, if no OP_Explain is coded, zero is returned.
+*/
+SQLITE_PRIVATE int sqlcipher_sqlite3WhereExplainBloomFilter(
+ const Parse *pParse, /* Parse context */
+ const WhereInfo *pWInfo, /* WHERE clause */
+ const WhereLevel *pLevel /* Bloom filter on this level */
+){
+ int ret = 0;
+ SrcItem *pItem = &pWInfo->pTabList->a[pLevel->iFrom];
+ Vdbe *v = pParse->pVdbe; /* VM being constructed */
+ sqlcipher_sqlite3 *db = pParse->db; /* Database handle */
+ char *zMsg; /* Text to add to EQP output */
+ int i; /* Loop counter */
+ WhereLoop *pLoop; /* The where loop */
+ StrAccum str; /* EQP output string */
+ char zBuf[100]; /* Initial space for EQP output string */
+
+ sqlcipher_sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH);
+ str.printfFlags = SQLITE_PRINTF_INTERNAL;
+ sqlcipher_sqlite3_str_appendf(&str, "BLOOM FILTER ON %S (", pItem);
+ pLoop = pLevel->pWLoop;
+ if( pLoop->wsFlags & WHERE_IPK ){
+ const Table *pTab = pItem->pTab;
+ if( pTab->iPKey>=0 ){
+ sqlcipher_sqlite3_str_appendf(&str, "%s=?", pTab->aCol[pTab->iPKey].zCnName);
+ }else{
+ sqlcipher_sqlite3_str_appendf(&str, "rowid=?");
+ }
+ }else{
+ for(i=pLoop->nSkip; i<pLoop->u.btree.nEq; i++){
+ const char *z = explainIndexColumnName(pLoop->u.btree.pIndex, i);
+ if( i>pLoop->nSkip ) sqlcipher_sqlite3_str_append(&str, " AND ", 5);
+ sqlcipher_sqlite3_str_appendf(&str, "%s=?", z);
+ }
+ }
+ sqlcipher_sqlite3_str_append(&str, ")", 1);
+ zMsg = sqlcipher_sqlite3StrAccumFinish(&str);
+ ret = sqlcipher_sqlite3VdbeAddOp4(v, OP_Explain, sqlcipher_sqlite3VdbeCurrentAddr(v),
+ pParse->addrExplain, 0, zMsg,P4_DYNAMIC);
+ return ret;
+}
#endif /* SQLITE_OMIT_EXPLAIN */
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
@@ -147259,7 +154965,7 @@ static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){
int nLoop = 0;
assert( pTerm!=0 );
while( (pTerm->wtFlags & TERM_CODED)==0
- && (pLevel->iLeftJoin==0 || ExprHasProperty(pTerm->pExpr, EP_FromJoin))
+ && (pLevel->iLeftJoin==0 || ExprHasProperty(pTerm->pExpr, EP_OuterON))
&& (pLevel->notReady & pTerm->prereqAll)==0
){
if( nLoop && (pTerm->wtFlags & TERM_LIKE)!=0 ){
@@ -147267,6 +154973,12 @@ static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){
}else{
pTerm->wtFlags |= TERM_CODED;
}
+#ifdef WHERETRACE_ENABLED
+ if( sqlcipher_sqlite3WhereTrace & 0x20000 ){
+ sqlcipher_sqlite3DebugPrintf("DISABLE-");
+ sqlcipher_sqlite3WhereTermPrint(pTerm, (int)(pTerm - (pTerm->pWC->a)));
+ }
+#endif
if( pTerm->iParent<0 ) break;
pTerm = &pTerm->pWC->a[pTerm->iParent];
assert( pTerm!=0 );
@@ -147380,16 +155092,23 @@ static Expr *removeUnindexableInClauseTerms(
Expr *pNew;
pNew = sqlcipher_sqlite3ExprDup(db, pX, 0);
if( db->mallocFailed==0 ){
- ExprList *pOrigRhs = pNew->x.pSelect->pEList; /* Original unmodified RHS */
- ExprList *pOrigLhs = pNew->pLeft->x.pList; /* Original unmodified LHS */
+ ExprList *pOrigRhs; /* Original unmodified RHS */
+ ExprList *pOrigLhs; /* Original unmodified LHS */
ExprList *pRhs = 0; /* New RHS after modifications */
ExprList *pLhs = 0; /* New LHS after mods */
int i; /* Loop counter */
Select *pSelect; /* Pointer to the SELECT on the RHS */
+ assert( ExprUseXSelect(pNew) );
+ pOrigRhs = pNew->x.pSelect->pEList;
+ assert( pNew->pLeft!=0 );
+ assert( ExprUseXList(pNew->pLeft) );
+ pOrigLhs = pNew->pLeft->x.pList;
for(i=iEq; i<pLoop->nLTerm; i++){
if( pLoop->aLTerm[i]->pExpr==pX ){
- int iField = pLoop->aLTerm[i]->u.x.iField - 1;
+ int iField;
+ assert( (pLoop->aLTerm[i]->eOperator & (WO_OR|WO_AND))==0 );
+ iField = pLoop->aLTerm[i]->u.x.iField - 1;
if( pOrigRhs->a[iField].pExpr==0 ) continue; /* Duplicate PK column */
pRhs = sqlcipher_sqlite3ExprListAppend(pParse, pRhs, pOrigRhs->a[iField].pExpr);
pOrigRhs->a[iField].pExpr = 0;
@@ -147504,19 +155223,25 @@ static int codeEqualityTerm(
}
iTab = 0;
- if( (pX->flags & EP_xIsSelect)==0 || pX->x.pSelect->pEList->nExpr==1 ){
+ if( !ExprUseXSelect(pX) || pX->x.pSelect->pEList->nExpr==1 ){
eType = sqlcipher_sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, 0, &iTab);
}else{
- sqlcipher_sqlite3 *db = pParse->db;
- pX = removeUnindexableInClauseTerms(pParse, iEq, pLoop, pX);
-
- if( !db->mallocFailed ){
- aiMap = (int*)sqlcipher_sqlite3DbMallocZero(pParse->db, sizeof(int)*nEq);
+ Expr *pExpr = pTerm->pExpr;
+ if( pExpr->iTable==0 || !ExprHasProperty(pExpr, EP_Subrtn) ){
+ sqlcipher_sqlite3 *db = pParse->db;
+ pX = removeUnindexableInClauseTerms(pParse, iEq, pLoop, pX);
+ if( !db->mallocFailed ){
+ aiMap = (int*)sqlcipher_sqlite3DbMallocZero(pParse->db, sizeof(int)*nEq);
+ eType = sqlcipher_sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap,&iTab);
+ pExpr->iTable = iTab;
+ }
+ sqlcipher_sqlite3ExprDelete(db, pX);
+ }else{
+ int n = sqlcipher_sqlite3ExprVectorSize(pX->pLeft);
+ aiMap = (int*)sqlcipher_sqlite3DbMallocZero(pParse->db, sizeof(int)*MAX(nEq,n));
eType = sqlcipher_sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap, &iTab);
- pTerm->pExpr->iTable = iTab;
}
- sqlcipher_sqlite3ExprDelete(db, pX);
- pX = pTerm->pExpr;
+ pX = pExpr;
}
if( eType==IN_INDEX_INDEX_DESC ){
@@ -147526,8 +155251,8 @@ static int codeEqualityTerm(
sqlcipher_sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0);
VdbeCoverageIf(v, bRev);
VdbeCoverageIf(v, !bRev);
- assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 );
+ assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 );
pLoop->wsFlags |= WHERE_IN_ABLE;
if( pLevel->u.in.nIn==0 ){
pLevel->addrNxt = sqlcipher_sqlite3VdbeMakeLabel(pParse);
@@ -147539,8 +155264,9 @@ static int codeEqualityTerm(
i = pLevel->u.in.nIn;
pLevel->u.in.nIn += nEq;
pLevel->u.in.aInLoop =
- sqlcipher_sqlite3DbReallocOrFree(pParse->db, pLevel->u.in.aInLoop,
- sizeof(pLevel->u.in.aInLoop[0])*pLevel->u.in.nIn);
+ sqlcipher_sqlite3WhereRealloc(pTerm->pWC->pWInfo,
+ pLevel->u.in.aInLoop,
+ sizeof(pLevel->u.in.aInLoop[0])*pLevel->u.in.nIn);
pIn = pLevel->u.in.aInLoop;
if( pIn ){
int iMap = 0; /* Index in aiMap[] */
@@ -147584,7 +155310,22 @@ static int codeEqualityTerm(
sqlcipher_sqlite3DbFree(pParse->db, aiMap);
#endif
}
- disableTerm(pLevel, pTerm);
+
+ /* As an optimization, try to disable the WHERE clause term that is
+ ** driving the index as it will always be true. The correct answer is
+ ** obtained regardless, but we might get the answer with fewer CPU cycles
+ ** by omitting the term.
+ **
+ ** But do not disable the term unless we are certain that the term is
+ ** not a transitive constraint. For an example of where that does not
+ ** work, see https://sqlite.org/forum/forumpost/eb8613976a (2021-05-04)
+ */
+ if( (pLevel->pWLoop->wsFlags & WHERE_TRANSCONS)==0
+ || (pTerm->eOperator & WO_EQUIV)==0
+ ){
+ disableTerm(pLevel, pTerm);
+ }
+
return iReg;
}
@@ -147670,11 +155411,13 @@ static int codeAllEqualityTerms(
if( nSkip ){
int iIdxCur = pLevel->iIdxCur;
+ sqlcipher_sqlite3VdbeAddOp3(v, OP_Null, 0, regBase, regBase+nSkip-1);
sqlcipher_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 = sqlcipher_sqlite3VdbeAddOp0(v, OP_Goto);
+ assert( pLevel->addrSkip==0 );
pLevel->addrSkip = sqlcipher_sqlite3VdbeAddOp4Int(v, (bRev?OP_SeekLT:OP_SeekGT),
iIdxCur, 0, regBase, nSkip);
VdbeCoverageIf(v, bRev==0);
@@ -147704,9 +155447,12 @@ static int codeAllEqualityTerms(
sqlcipher_sqlite3ReleaseTempReg(pParse, regBase);
regBase = r1;
}else{
- sqlcipher_sqlite3VdbeAddOp2(v, OP_SCopy, r1, regBase+j);
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_Copy, r1, regBase+j);
}
}
+ }
+ for(j=nSkip; j<nEq; j++){
+ pTerm = pLoop->aLTerm[j];
if( pTerm->eOperator & WO_IN ){
if( pTerm->pExpr->flags & EP_xIsSelect ){
/* No affinity ever needs to be (or should be) applied to a value
@@ -147721,7 +155467,8 @@ static int codeAllEqualityTerms(
sqlcipher_sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->addrBrk);
VdbeCoverage(v);
}
- if( zAff ){
+ if( pParse->nErr==0 ){
+ assert( pParse->db->mallocFailed==0 );
if( sqlcipher_sqlite3CompareAffinity(pRight, zAff[j])==SQLITE_AFF_BLOB ){
zAff[j] = SQLITE_AFF_BLOB;
}
@@ -147884,7 +155631,7 @@ static int codeCursorHintFixExpr(Walker *pWalker, Expr *pExpr){
** Insert an OP_CursorHint instruction if it is appropriate to do so.
*/
static void codeCursorHint(
- struct SrcList_item *pTabItem, /* FROM clause item */
+ SrcItem *pTabItem, /* FROM clause item */
WhereInfo *pWInfo, /* The where clause */
WhereLevel *pLevel, /* Which loop to provide hints for */
WhereTerm *pEndRange /* Hint this end-of-scan boundary term if not NULL */
@@ -147911,7 +155658,7 @@ static void codeCursorHint(
sWalker.pParse = pParse;
sWalker.u.pCCurHint = &sHint;
pWC = &pWInfo->sWC;
- for(i=0; i<pWC->nTerm; i++){
+ for(i=0; i<pWC->nBase; i++){
pTerm = &pWC->a[i];
if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
if( pTerm->prereqAll & pLevel->notReady ) continue;
@@ -147940,8 +155687,8 @@ static void codeCursorHint(
*/
if( pTabItem->fg.jointype & JT_LEFT ){
Expr *pExpr = pTerm->pExpr;
- if( !ExprHasProperty(pExpr, EP_FromJoin)
- || pExpr->iRightJoinTable!=pTabItem->iCursor
+ if( !ExprHasProperty(pExpr, EP_OuterON)
+ || pExpr->w.iJoin!=pTabItem->iCursor
){
sWalker.eCode = 0;
sWalker.xExprCallback = codeCursorHintIsOrFunction;
@@ -147949,7 +155696,7 @@ static void codeCursorHint(
if( sWalker.eCode ) continue;
}
}else{
- if( ExprHasProperty(pTerm->pExpr, EP_FromJoin) ) continue;
+ if( ExprHasProperty(pTerm->pExpr, EP_OuterON) ) continue;
}
/* All terms in pWLoop->aLTerm[] except pEndRange are used to initialize
@@ -147997,13 +155744,21 @@ static void codeCursorHint(
**
** OP_DeferredSeek $iCur $iRowid
**
+** Which causes a seek on $iCur to the row with rowid $iRowid.
+**
** However, if the scan currently being coded is a branch of an OR-loop and
-** the statement currently being coded is a SELECT, then P3 of OP_DeferredSeek
-** is set to iIdxCur and P4 is set to point to an array of integers
-** containing one entry for each column of the table cursor iCur is open
-** on. For each table column, if the column is the i'th column of the
-** index, then the corresponding array entry is set to (i+1). If the column
-** does not appear in the index at all, the array entry is set to 0.
+** the statement currently being coded is a SELECT, then additional information
+** is added that might allow OP_Column to omit the seek and instead do its
+** lookup on the index, thus avoiding an expensive seek operation. To
+** enable this optimization, the P3 of OP_DeferredSeek is set to iIdxCur
+** and P4 is set to an array of integers containing one entry for each column
+** in the table. For each table column, if the column is the i'th
+** column of the index, then the corresponding array entry is set to (i+1).
+** If the column does not appear in the index at all, the array entry is set
+** to 0. The OP_Column opcode can check this array to see if the column it
+** wants is in the index and if it is, it will substitute the index cursor
+** and column number and continue with those new values, rather than seeking
+** the table cursor.
*/
static void codeDeferredSeek(
WhereInfo *pWInfo, /* Where clause context */
@@ -148019,7 +155774,7 @@ static void codeDeferredSeek(
pWInfo->bDeferredSeek = 1;
sqlcipher_sqlite3VdbeAddOp3(v, OP_DeferredSeek, iIdxCur, 0, iCur);
- if( (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)
+ if( (pWInfo->wctrlFlags & (WHERE_OR_SUBCLAUSE|WHERE_RIGHT_JOIN))
&& DbMaskAllZero(sqlcipher_sqlite3ParseToplevel(pParse)->writeMask)
){
int i;
@@ -148053,7 +155808,7 @@ static void codeExprOrVector(Parse *pParse, Expr *p, int iReg, int nReg){
assert( nReg>0 );
if( p && sqlcipher_sqlite3ExprIsVector(p) ){
#ifndef SQLITE_OMIT_SUBQUERY
- if( (p->flags & EP_xIsSelect) ){
+ if( ExprUseXSelect(p) ){
Vdbe *v = pParse->pVdbe;
int iSelect;
assert( p->op==TK_SELECT );
@@ -148063,14 +155818,16 @@ static void codeExprOrVector(Parse *pParse, Expr *p, int iReg, int nReg){
#endif
{
int i;
- ExprList *pList = p->x.pList;
+ const ExprList *pList;
+ assert( ExprUseXList(p) );
+ pList = p->x.pList;
assert( nReg<=pList->nExpr );
for(i=0; i<nReg; i++){
sqlcipher_sqlite3ExprCode(pParse, pList->a[i].pExpr, iReg+i);
}
}
}else{
- assert( nReg==1 );
+ assert( nReg==1 || pParse->nErr );
sqlcipher_sqlite3ExprCode(pParse, p, iReg);
}
}
@@ -148111,15 +155868,15 @@ static void preserveExpr(IdxExprTrans *pTrans, Expr *pExpr){
static int whereIndexExprTransNode(Walker *p, Expr *pExpr){
IdxExprTrans *pX = p->u.pIdxTrans;
if( sqlcipher_sqlite3ExprCompare(0, pExpr, pX->pIdxExpr, pX->iTabCur)==0 ){
+ pExpr = sqlcipher_sqlite3ExprSkipCollate(pExpr);
preserveExpr(pX, pExpr);
pExpr->affExpr = sqlcipher_sqlite3ExprAffinity(pExpr);
pExpr->op = TK_COLUMN;
pExpr->iTable = pX->iIdxCur;
pExpr->iColumn = pX->iIdxCol;
- pExpr->y.pTab = 0;
- testcase( ExprHasProperty(pExpr, EP_Skip) );
testcase( ExprHasProperty(pExpr, EP_Unlikely) );
- ExprClearProperty(pExpr, EP_Skip|EP_Unlikely);
+ ExprClearProperty(pExpr, EP_Skip|EP_Unlikely|EP_WinFunc|EP_Subrtn);
+ pExpr->y.pTab = 0;
return WRC_Prune;
}else{
return WRC_Continue;
@@ -148134,7 +155891,7 @@ static int whereIndexExprTransColumn(Walker *p, Expr *pExpr){
if( pExpr->op==TK_COLUMN ){
IdxExprTrans *pX = p->u.pIdxTrans;
if( pExpr->iTable==pX->iTabCur && pExpr->iColumn==pX->iTabCol ){
- assert( pExpr->y.pTab!=0 );
+ assert( ExprUseYTab(pExpr) && pExpr->y.pTab!=0 );
preserveExpr(pX, pExpr);
pExpr->affExpr = sqlcipher_sqlite3TableColumnAffinity(pExpr->y.pTab,pExpr->iColumn);
pExpr->iTable = pX->iIdxCur;
@@ -148182,15 +155939,16 @@ static void whereIndexExprTrans(
for(iIdxCol=0; iIdxCol<pIdx->nColumn; iIdxCol++){
i16 iRef = pIdx->aiColumn[iIdxCol];
if( iRef==XN_EXPR ){
- assert( aColExpr->a[iIdxCol].pExpr!=0 );
+ assert( aColExpr!=0 && aColExpr->a[iIdxCol].pExpr!=0 );
x.pIdxExpr = aColExpr->a[iIdxCol].pExpr;
if( sqlcipher_sqlite3ExprIsConstant(x.pIdxExpr) ) continue;
w.xExprCallback = whereIndexExprTransNode;
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
}else if( iRef>=0
&& (pTab->aCol[iRef].colFlags & COLFLAG_VIRTUAL)!=0
- && (pTab->aCol[iRef].zColl==0
- || sqlcipher_sqlite3StrICmp(pTab->aCol[iRef].zColl, sqlcipher_sqlite3StrBINARY)==0)
+ && ((pTab->aCol[iRef].colFlags & COLFLAG_HASCOLL)==0
+ || sqlcipher_sqlite3StrICmp(sqlcipher_sqlite3ColumnColl(&pTab->aCol[iRef]),
+ sqlcipher_sqlite3StrBINARY)==0)
){
/* Check to see if there are direct references to generated columns
** that are contained in the index. Pulling the generated column
@@ -148240,6 +155998,68 @@ static void whereApplyPartialIndexConstraints(
}
/*
+** This routine is called right after An OP_Filter has been generated and
+** before the corresponding index search has been performed. This routine
+** checks to see if there are additional Bloom filters in inner loops that
+** can be checked prior to doing the index lookup. If there are available
+** inner-loop Bloom filters, then evaluate those filters now, before the
+** index lookup. The idea is that a Bloom filter check is way faster than
+** an index lookup, and the Bloom filter might return false, meaning that
+** the index lookup can be skipped.
+**
+** We know that an inner loop uses a Bloom filter because it has the
+** WhereLevel.regFilter set. If an inner-loop Bloom filter is checked,
+** then clear the WhereLevel.regFilter value to prevent the Bloom filter
+** from being checked a second time when the inner loop is evaluated.
+*/
+static SQLITE_NOINLINE void filterPullDown(
+ Parse *pParse, /* Parsing context */
+ WhereInfo *pWInfo, /* Complete information about the WHERE clause */
+ int iLevel, /* Which level of pWInfo->a[] should be coded */
+ int addrNxt, /* Jump here to bypass inner loops */
+ Bitmask notReady /* Loops that are not ready */
+){
+ while( ++iLevel < pWInfo->nLevel ){
+ WhereLevel *pLevel = &pWInfo->a[iLevel];
+ WhereLoop *pLoop = pLevel->pWLoop;
+ if( pLevel->regFilter==0 ) continue;
+ if( pLevel->pWLoop->nSkip ) continue;
+ /* ,--- Because sqlcipher_sqlite3ConstructBloomFilter() has will not have set
+ ** vvvvv--' pLevel->regFilter if this were true. */
+ if( NEVER(pLoop->prereq & notReady) ) continue;
+ assert( pLevel->addrBrk==0 );
+ pLevel->addrBrk = addrNxt;
+ if( pLoop->wsFlags & WHERE_IPK ){
+ WhereTerm *pTerm = pLoop->aLTerm[0];
+ int regRowid;
+ assert( pTerm!=0 );
+ assert( pTerm->pExpr!=0 );
+ testcase( pTerm->wtFlags & TERM_VIRTUAL );
+ regRowid = sqlcipher_sqlite3GetTempReg(pParse);
+ regRowid = codeEqualityTerm(pParse, pTerm, pLevel, 0, 0, regRowid);
+ sqlcipher_sqlite3VdbeAddOp4Int(pParse->pVdbe, OP_Filter, pLevel->regFilter,
+ addrNxt, regRowid, 1);
+ VdbeCoverage(pParse->pVdbe);
+ }else{
+ u16 nEq = pLoop->u.btree.nEq;
+ int r1;
+ char *zStartAff;
+
+ assert( pLoop->wsFlags & WHERE_INDEXED );
+ assert( (pLoop->wsFlags & WHERE_COLUMN_IN)==0 );
+ r1 = codeAllEqualityTerms(pParse,pLevel,0,0,&zStartAff);
+ codeApplyAffinity(pParse, r1, nEq, zStartAff);
+ sqlcipher_sqlite3DbFree(pParse->db, zStartAff);
+ sqlcipher_sqlite3VdbeAddOp4Int(pParse->pVdbe, OP_Filter, pLevel->regFilter,
+ addrNxt, r1, nEq);
+ VdbeCoverage(pParse->pVdbe);
+ }
+ pLevel->regFilter = 0;
+ pLevel->addrBrk = 0;
+ }
+}
+
+/*
** Generate code for the start of the iLevel-th loop in the WHERE clause
** implementation described by pWInfo.
*/
@@ -148259,7 +156079,7 @@ SQLITE_PRIVATE Bitmask sqlcipher_sqlite3WhereCodeOneLoopStart(
WhereClause *pWC; /* Decomposition of the entire WHERE clause */
WhereTerm *pTerm; /* A WHERE clause term */
sqlcipher_sqlite3 *db; /* Database connection */
- struct SrcList_item *pTabItem; /* FROM clause term being coded */
+ SrcItem *pTabItem; /* FROM clause term being coded */
int addrBrk; /* Jump here to break out of the loop */
int addrHalt; /* addrBrk for the outermost loop */
int addrCont; /* Jump here to continue with next cycle */
@@ -148309,7 +156129,7 @@ SQLITE_PRIVATE Bitmask sqlcipher_sqlite3WhereCodeOneLoopStart(
** initialize a memory cell that records if this table matches any
** row of the left table of the join.
*/
- assert( (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)
+ assert( (pWInfo->wctrlFlags & (WHERE_OR_SUBCLAUSE|WHERE_RIGHT_JOIN))
|| pLevel->iFrom>0 || (pTabItem[0].fg.jointype & JT_LEFT)==0
);
if( pLevel->iFrom>0 && (pTabItem[0].fg.jointype & JT_LEFT)!=0 ){
@@ -148320,7 +156140,10 @@ SQLITE_PRIVATE Bitmask sqlcipher_sqlite3WhereCodeOneLoopStart(
/* Compute a safe address to jump to if we discover that the table for
** this loop is empty and can never contribute content. */
- for(j=iLevel; j>0 && pWInfo->a[j].iLeftJoin==0; j--){}
+ for(j=iLevel; j>0; j--){
+ if( pWInfo->a[j].iLeftJoin ) break;
+ if( pWInfo->a[j].pRJ ) break;
+ }
addrHalt = pWInfo->a[j].addrBrk;
/* Special case of a FROM clause subquery implemented as a co-routine */
@@ -148341,7 +156164,6 @@ SQLITE_PRIVATE Bitmask sqlcipher_sqlite3WhereCodeOneLoopStart(
int iReg; /* P3 Value for OP_VFilter */
int addrNotFound;
int nConstraint = pLoop->nLTerm;
- int iIn; /* Counter for IN constraints */
iReg = sqlcipher_sqlite3GetTempRange(pParse, nConstraint+2);
addrNotFound = pLevel->addrBrk;
@@ -148350,11 +156172,27 @@ SQLITE_PRIVATE Bitmask sqlcipher_sqlite3WhereCodeOneLoopStart(
pTerm = pLoop->aLTerm[j];
if( NEVER(pTerm==0) ) continue;
if( pTerm->eOperator & WO_IN ){
- codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, iTarget);
- addrNotFound = pLevel->addrNxt;
+ if( SMASKBIT32(j) & pLoop->u.vtab.mHandleIn ){
+ int iTab = pParse->nTab++;
+ int iCache = ++pParse->nMem;
+ sqlcipher_sqlite3CodeRhsOfIN(pParse, pTerm->pExpr, iTab);
+ sqlcipher_sqlite3VdbeAddOp3(v, OP_VInitIn, iTab, iTarget, iCache);
+ }else{
+ codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, iTarget);
+ addrNotFound = pLevel->addrNxt;
+ }
}else{
Expr *pRight = pTerm->pExpr->pRight;
codeExprOrVector(pParse, pRight, iTarget, 1);
+ if( pTerm->eMatchOp==SQLITE_INDEX_CONSTRAINT_OFFSET
+ && pLoop->u.vtab.bOmitOffset
+ ){
+ assert( pTerm->eOperator==WO_AUX );
+ assert( pWInfo->pLimit!=0 );
+ assert( pWInfo->pLimit->iOffset>0 );
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_Integer, 0, pWInfo->pLimit->iOffset);
+ VdbeComment((v,"Zero OFFSET counter"));
+ }
}
}
sqlcipher_sqlite3VdbeAddOp2(v, OP_Integer, pLoop->u.vtab.idxNum, iReg);
@@ -148370,40 +156208,55 @@ SQLITE_PRIVATE Bitmask sqlcipher_sqlite3WhereCodeOneLoopStart(
pLevel->p1 = iCur;
pLevel->op = pWInfo->eOnePass ? OP_Noop : OP_VNext;
pLevel->p2 = sqlcipher_sqlite3VdbeCurrentAddr(v);
- iIn = pLevel->u.in.nIn;
- for(j=nConstraint-1; j>=0; j--){
+ assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 );
+
+ for(j=0; j<nConstraint; j++){
pTerm = pLoop->aLTerm[j];
- if( (pTerm->eOperator & WO_IN)!=0 ) iIn--;
if( j<16 && (pLoop->u.vtab.omitMask>>j)&1 ){
disableTerm(pLevel, pTerm);
- }else if( (pTerm->eOperator & WO_IN)!=0
- && sqlcipher_sqlite3ExprVectorSize(pTerm->pExpr->pLeft)==1
+ continue;
+ }
+ if( (pTerm->eOperator & WO_IN)!=0
+ && (SMASKBIT32(j) & pLoop->u.vtab.mHandleIn)==0
+ && !db->mallocFailed
){
Expr *pCompare; /* The comparison operator */
Expr *pRight; /* RHS of the comparison */
VdbeOp *pOp; /* Opcode to access the value of the IN constraint */
+ int iIn; /* IN loop corresponding to the j-th constraint */
/* Reload the constraint value into reg[iReg+j+2]. The same value
** was loaded into the same register prior to the OP_VFilter, but
** the xFilter implementation might have changed the datatype or
- ** encoding of the value in the register, so it *must* be reloaded. */
- assert( pLevel->u.in.aInLoop!=0 || db->mallocFailed );
- if( !db->mallocFailed ){
- assert( iIn>=0 && iIn<pLevel->u.in.nIn );
+ ** encoding of the value in the register, so it *must* be reloaded.
+ */
+ for(iIn=0; ALWAYS(iIn<pLevel->u.in.nIn); iIn++){
pOp = sqlcipher_sqlite3VdbeGetOp(v, pLevel->u.in.aInLoop[iIn].addrInTop);
- assert( pOp->opcode==OP_Column || pOp->opcode==OP_Rowid );
- assert( pOp->opcode!=OP_Column || pOp->p3==iReg+j+2 );
- assert( pOp->opcode!=OP_Rowid || pOp->p2==iReg+j+2 );
- testcase( pOp->opcode==OP_Rowid );
- sqlcipher_sqlite3VdbeAddOp3(v, pOp->opcode, pOp->p1, pOp->p2, pOp->p3);
+ if( (pOp->opcode==OP_Column && pOp->p3==iReg+j+2)
+ || (pOp->opcode==OP_Rowid && pOp->p2==iReg+j+2)
+ ){
+ testcase( pOp->opcode==OP_Rowid );
+ sqlcipher_sqlite3VdbeAddOp3(v, pOp->opcode, pOp->p1, pOp->p2, pOp->p3);
+ break;
+ }
}
/* Generate code that will continue to the next row if
- ** the IN constraint is not satisfied */
+ ** the IN constraint is not satisfied
+ */
pCompare = sqlcipher_sqlite3PExpr(pParse, TK_EQ, 0, 0);
- assert( pCompare!=0 || db->mallocFailed );
- if( pCompare ){
- pCompare->pLeft = pTerm->pExpr->pLeft;
+ if( !db->mallocFailed ){
+ int iFld = pTerm->u.x.iField;
+ Expr *pLeft = pTerm->pExpr->pLeft;
+ assert( pLeft!=0 );
+ if( iFld>0 ){
+ assert( pLeft->op==TK_VECTOR );
+ assert( ExprUseXList(pLeft) );
+ assert( iFld<=pLeft->x.pList->nExpr );
+ pCompare->pLeft = pLeft->x.pList->a[iFld-1].pExpr;
+ }else{
+ pCompare->pLeft = pLeft;
+ }
pCompare->pRight = pRight = sqlcipher_sqlite3Expr(db, TK_REGISTER, 0);
if( pRight ){
pRight->iTable = iReg+j+2;
@@ -148412,11 +156265,11 @@ SQLITE_PRIVATE Bitmask sqlcipher_sqlite3WhereCodeOneLoopStart(
);
}
pCompare->pLeft = 0;
- sqlcipher_sqlite3ExprDelete(db, pCompare);
}
+ sqlcipher_sqlite3ExprDelete(db, pCompare);
}
}
- assert( iIn==0 || db->mallocFailed );
+
/* These registers need to be preserved in case there is an IN operator
** loop. So we could deallocate the registers here (and potentially
** reuse them later) if (pLoop->wsFlags & WHERE_IN_ABLE)==0. But it seems
@@ -148444,12 +156297,15 @@ SQLITE_PRIVATE Bitmask sqlcipher_sqlite3WhereCodeOneLoopStart(
iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, 0, bRev, iReleaseReg);
if( iRowidReg!=iReleaseReg ) sqlcipher_sqlite3ReleaseTempReg(pParse, iReleaseReg);
addrNxt = pLevel->addrNxt;
+ if( pLevel->regFilter ){
+ sqlcipher_sqlite3VdbeAddOp4Int(v, OP_Filter, pLevel->regFilter, addrNxt,
+ iRowidReg, 1);
+ VdbeCoverage(v);
+ filterPullDown(pParse, pWInfo, iLevel, addrNxt, notReady);
+ }
sqlcipher_sqlite3VdbeAddOp3(v, OP_SeekRowid, iCur, addrNxt, iRowidReg);
VdbeCoverage(v);
pLevel->op = OP_Noop;
- if( (pTerm->prereqAll & pLevel->notReady)==0 ){
- pTerm->wtFlags |= TERM_CODED;
- }
}else if( (pLoop->wsFlags & WHERE_IPK)!=0
&& (pLoop->wsFlags & WHERE_COLUMN_RANGE)!=0
){
@@ -148697,14 +156553,18 @@ SQLITE_PRIVATE Bitmask sqlcipher_sqlite3WhereCodeOneLoopStart(
** a forward order scan on a descending index, interchange the
** start and end terms (pRangeStart and pRangeEnd).
*/
- if( (nEq<pIdx->nKeyCol && bRev==(pIdx->aSortOrder[nEq]==SQLITE_SO_ASC))
- || (bRev && pIdx->nKeyCol==nEq)
- ){
+ if( (nEq<pIdx->nColumn && bRev==(pIdx->aSortOrder[nEq]==SQLITE_SO_ASC)) ){
SWAP(WhereTerm *, pRangeEnd, pRangeStart);
SWAP(u8, bSeekPastNull, bStopAtNull);
SWAP(u8, nBtm, nTop);
}
+ if( iLevel>0 && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)!=0 ){
+ /* In case OP_SeekScan is used, ensure that the index cursor does not
+ ** point to a valid row for the first iteration of this loop. */
+ sqlcipher_sqlite3VdbeAddOp1(v, OP_NullRow, iIdxCur);
+ }
+
/* 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.
@@ -148768,6 +156628,12 @@ SQLITE_PRIVATE Bitmask sqlcipher_sqlite3WhereCodeOneLoopStart(
sqlcipher_sqlite3VdbeAddOp2(v, OP_Integer, 1, regBignull);
VdbeComment((v, "NULL-scan pass ctr"));
}
+ if( pLevel->regFilter ){
+ sqlcipher_sqlite3VdbeAddOp4Int(v, OP_Filter, pLevel->regFilter, addrNxt,
+ regBase, nEq);
+ VdbeCoverage(v);
+ filterPullDown(pParse, pWInfo, iLevel, addrNxt, notReady);
+ }
op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev];
assert( op!=0 );
@@ -148816,8 +156682,19 @@ SQLITE_PRIVATE Bitmask sqlcipher_sqlite3WhereCodeOneLoopStart(
** range (if any).
*/
nConstraint = nEq;
+ assert( pLevel->p2==0 );
if( pRangeEnd ){
Expr *pRight = pRangeEnd->pExpr->pRight;
+ if( addrSeekScan ){
+ /* For a seek-scan that has a range on the lowest term of the index,
+ ** we have to make the top of the loop be code that sets the end
+ ** condition of the range. Otherwise, the OP_SeekScan might jump
+ ** over that initialization, leaving the range-end value set to the
+ ** range-start value, resulting in a wrong answer.
+ ** See ticket 5981a8c041a3c2f3 (2021-11-02).
+ */
+ pLevel->p2 = sqlcipher_sqlite3VdbeCurrentAddr(v);
+ }
codeExprOrVector(pParse, pRight, regBase+nEq, nTop);
whereLikeOptimizationStringFixup(v, pLevel, pRangeEnd);
if( (pRangeEnd->wtFlags & TERM_VNULL)==0
@@ -148851,7 +156728,7 @@ SQLITE_PRIVATE Bitmask sqlcipher_sqlite3WhereCodeOneLoopStart(
sqlcipher_sqlite3DbFree(db, zEndAff);
/* Top of the loop body */
- pLevel->p2 = sqlcipher_sqlite3VdbeCurrentAddr(v);
+ if( pLevel->p2==0 ) pLevel->p2 = sqlcipher_sqlite3VdbeCurrentAddr(v);
/* Check if the index cursor is past the end of the range. */
if( nConstraint ){
@@ -148893,7 +156770,7 @@ SQLITE_PRIVATE Bitmask sqlcipher_sqlite3WhereCodeOneLoopStart(
/* Seek the table cursor, if required */
omitTable = (pLoop->wsFlags & WHERE_IDX_ONLY)!=0
- && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0;
+ && (pWInfo->wctrlFlags & (WHERE_OR_SUBCLAUSE|WHERE_RIGHT_JOIN))==0;
if( omitTable ){
/* pIdx is a covering index. No need to access the main table. */
}else if( HasRowid(pIdx->pTable) ){
@@ -148927,7 +156804,7 @@ SQLITE_PRIVATE Bitmask sqlcipher_sqlite3WhereCodeOneLoopStart(
** move forward to the next index.
** https://sqlite.org/src/info/4e8e4857d32d401f
*/
- if( (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0 ){
+ if( (pWInfo->wctrlFlags & (WHERE_OR_SUBCLAUSE|WHERE_RIGHT_JOIN))==0 ){
whereIndexExprTrans(pIdx, iCur, iIdxCur, pWInfo);
}
@@ -148946,7 +156823,7 @@ SQLITE_PRIVATE Bitmask sqlcipher_sqlite3WhereCodeOneLoopStart(
/* The following assert() is not a requirement, merely an observation:
** The OR-optimization doesn't work for the right hand table of
** a LEFT JOIN: */
- assert( (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0 );
+ assert( (pWInfo->wctrlFlags & (WHERE_OR_SUBCLAUSE|WHERE_RIGHT_JOIN))==0 );
}
/* Record the instruction used to terminate the loop. */
@@ -149041,7 +156918,7 @@ SQLITE_PRIVATE Bitmask sqlcipher_sqlite3WhereCodeOneLoopStart(
*/
if( pWInfo->nLevel>1 ){
int nNotReady; /* The number of notReady tables */
- struct SrcList_item *origSrc; /* Original list of tables */
+ SrcItem *origSrc; /* Original list of tables */
nNotReady = pWInfo->nLevel - iLevel - 1;
pOrTab = sqlcipher_sqlite3StackAllocRaw(db,
sizeof(*pOrTab)+ nNotReady*sizeof(pOrTab->a[0]));
@@ -149084,7 +156961,7 @@ SQLITE_PRIVATE Bitmask sqlcipher_sqlite3WhereCodeOneLoopStart(
iRetInit = sqlcipher_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
+ ** Then for every term xN, evaluate as the subexpression: xN AND y
** That way, terms in y that are factored into the disjunction will
** be picked up by the recursive calls to sqlcipher_sqlite3WhereBegin() below.
**
@@ -149096,6 +156973,20 @@ SQLITE_PRIVATE Bitmask sqlcipher_sqlite3WhereCodeOneLoopStart(
** 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
+ **
+ ** 2022-02-04: Do not push down slices of a row-value comparison.
+ ** In other words, "w" or "y" may not be a slice of a vector. Otherwise,
+ ** the initialization of the right-hand operand of the vector comparison
+ ** might not occur, or might occur only in an OR branch that is not
+ ** taken. dbsqlfuzz 80a9fade844b4fb43564efc972bcb2c68270f5d1.
+ **
+ ** 2022-03-03: Do not push down expressions that involve subqueries.
+ ** The subquery might get coded as a subroutine. Any table-references
+ ** in the subquery might be resolved to index-references for the index on
+ ** the OR branch in which the subroutine is coded. But if the subroutine
+ ** is invoked from a different OR branch that uses a different index, such
+ ** index-references will not work. tag-20220303a
+ ** https://sqlite.org/forum/forumpost/36937b197273d403
*/
if( pWC->nTerm>1 ){
int iTerm;
@@ -149104,9 +156995,12 @@ SQLITE_PRIVATE Bitmask sqlcipher_sqlite3WhereCodeOneLoopStart(
if( &pWC->a[iTerm] == pTerm ) continue;
testcase( pWC->a[iTerm].wtFlags & TERM_VIRTUAL );
testcase( pWC->a[iTerm].wtFlags & TERM_CODED );
- if( (pWC->a[iTerm].wtFlags & (TERM_VIRTUAL|TERM_CODED))!=0 ) continue;
+ testcase( pWC->a[iTerm].wtFlags & TERM_SLICE );
+ if( (pWC->a[iTerm].wtFlags & (TERM_VIRTUAL|TERM_CODED|TERM_SLICE))!=0 ){
+ continue;
+ }
if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue;
- testcase( pWC->a[iTerm].wtFlags & TERM_ORINFO );
+ if( ExprHasProperty(pExpr, EP_Subquery) ) continue; /* tag-20220303a */
pExpr = sqlcipher_sqlite3ExprDup(db, pExpr, 0);
pAndExpr = sqlcipher_sqlite3ExprAnd(pParse, pAndExpr, pExpr);
}
@@ -149114,7 +157008,7 @@ SQLITE_PRIVATE Bitmask sqlcipher_sqlite3WhereCodeOneLoopStart(
/* The extra 0x10000 bit on the opcode is masked off and does not
** become part of the new Expr.op. However, it does make the
** op==TK_AND comparison inside of sqlcipher_sqlite3PExpr() false, and this
- ** prevents sqlcipher_sqlite3PExpr() from implementing AND short-circuit
+ ** prevents sqlcipher_sqlite3PExpr() from applying the AND short-circuit
** optimization, which we do not want here. */
pAndExpr = sqlcipher_sqlite3PExpr(pParse, TK_AND|0x10000, 0, pAndExpr);
}
@@ -149130,10 +157024,16 @@ SQLITE_PRIVATE Bitmask sqlcipher_sqlite3WhereCodeOneLoopStart(
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 */
+ Expr *pDelete; /* Local copy of OR clause term */
int jmp1 = 0; /* Address of jump operation */
testcase( (pTabItem[0].fg.jointype & JT_LEFT)!=0
- && !ExprHasProperty(pOrExpr, EP_FromJoin)
+ && !ExprHasProperty(pOrExpr, EP_OuterON)
); /* See TH3 vtab25.400 and ticket 614b25314c766238 */
+ pDelete = pOrExpr = sqlcipher_sqlite3ExprDup(db, pOrExpr, 0);
+ if( db->mallocFailed ){
+ sqlcipher_sqlite3ExprDelete(db, pDelete);
+ continue;
+ }
if( pAndExpr ){
pAndExpr->pLeft = pOrExpr;
pOrExpr = pAndExpr;
@@ -149141,9 +157041,9 @@ SQLITE_PRIVATE Bitmask sqlcipher_sqlite3WhereCodeOneLoopStart(
/* Loop through table entries that match term pOrTerm. */
ExplainQueryPlan((pParse, 1, "INDEX %d", ii+1));
WHERETRACE(0xffff, ("Subplan for OR-clause:\n"));
- pSubWInfo = sqlcipher_sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0,
+ pSubWInfo = sqlcipher_sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0, 0,
WHERE_OR_SUBCLAUSE, iCovCur);
- assert( pSubWInfo || pParse->nErr || db->mallocFailed );
+ assert( pSubWInfo || pParse->nErr );
if( pSubWInfo ){
WhereLoop *pSubLoop;
int addrExplain = sqlcipher_sqlite3WhereExplainOneScan(
@@ -149248,10 +157148,14 @@ SQLITE_PRIVATE Bitmask sqlcipher_sqlite3WhereCodeOneLoopStart(
sqlcipher_sqlite3WhereEnd(pSubWInfo);
ExplainQueryPlanPop(pParse);
}
+ sqlcipher_sqlite3ExprDelete(db, pDelete);
}
}
ExplainQueryPlanPop(pParse);
- pLevel->u.pCovidx = pCov;
+ assert( pLevel->pWLoop==pLoop );
+ assert( (pLoop->wsFlags & WHERE_MULTI_OR)!=0 );
+ assert( (pLoop->wsFlags & WHERE_IN_ABLE)==0 );
+ pLevel->u.pCoveringIdx = pCov;
if( pCov ) pLevel->iIdxCur = iCovCur;
if( pAndExpr ){
pAndExpr->pLeft = 0;
@@ -149261,6 +157165,14 @@ SQLITE_PRIVATE Bitmask sqlcipher_sqlite3WhereCodeOneLoopStart(
sqlcipher_sqlite3VdbeGoto(v, pLevel->addrBrk);
sqlcipher_sqlite3VdbeResolveLabel(v, iLoopBody);
+ /* Set the P2 operand of the OP_Return opcode that will end the current
+ ** loop to point to this spot, which is the top of the next containing
+ ** loop. The byte-code formatter will use that P2 value as a hint to
+ ** indent everything in between the this point and the final OP_Return.
+ ** See tag-20220407a in vdbe.c and shell.c */
+ assert( pLevel->op==OP_Return );
+ pLevel->p2 = sqlcipher_sqlite3VdbeCurrentAddr(v);
+
if( pWInfo->nLevel>1 ){ sqlcipher_sqlite3StackFree(db, pOrTab); }
if( !untestedTerms ) disableTerm(pLevel, pTerm);
}else
@@ -149323,10 +157235,22 @@ SQLITE_PRIVATE Bitmask sqlcipher_sqlite3WhereCodeOneLoopStart(
}
pE = pTerm->pExpr;
assert( pE!=0 );
- if( (pTabItem->fg.jointype&JT_LEFT) && !ExprHasProperty(pE,EP_FromJoin) ){
- continue;
+ if( pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT) ){
+ if( !ExprHasProperty(pE,EP_OuterON|EP_InnerON) ){
+ /* Defer processing WHERE clause constraints until after outer
+ ** join processing. tag-20220513a */
+ continue;
+ }else if( (pTabItem->fg.jointype & JT_LEFT)==JT_LEFT
+ && !ExprHasProperty(pE,EP_OuterON) ){
+ continue;
+ }else{
+ Bitmask m = sqlcipher_sqlite3WhereGetMask(&pWInfo->sMaskSet, pE->w.iJoin);
+ if( m & pLevel->notReady ){
+ /* An ON clause that is not ripe */
+ continue;
+ }
+ }
}
-
if( iLoop==1 && !sqlcipher_sqlite3ExprCoveredByIndex(pE, pLevel->iTabCur, pIdx) ){
iNext = 2;
continue;
@@ -149378,14 +157302,14 @@ SQLITE_PRIVATE Bitmask sqlcipher_sqlite3WhereCodeOneLoopStart(
** 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++){
+ for(pTerm=pWC->a, j=pWC->nBase; j>0; j--, pTerm++){
Expr *pE, sEAlt;
WhereTerm *pAlt;
if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) continue;
if( (pTerm->eOperator & WO_EQUIV)==0 ) continue;
if( pTerm->leftCursor!=iCur ) continue;
- if( pTabItem->fg.jointype & JT_LEFT ) continue;
+ if( pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT) ) continue;
pE = pTerm->pExpr;
#ifdef WHERETRACE_ENABLED /* 0x800 */
if( sqlcipher_sqlite3WhereTrace & 0x800 ){
@@ -149393,14 +157317,15 @@ SQLITE_PRIVATE Bitmask sqlcipher_sqlite3WhereCodeOneLoopStart(
sqlcipher_sqlite3WhereTermPrint(pTerm, pWC->nTerm-j);
}
#endif
- assert( !ExprHasProperty(pE, EP_FromJoin) );
+ assert( !ExprHasProperty(pE, EP_OuterON) );
assert( (pTerm->prereqRight & pLevel->notReady)!=0 );
+ assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
pAlt = sqlcipher_sqlite3WhereFindTerm(pWC, iCur, pTerm->u.x.leftColumn, notReady,
WO_EQ|WO_IN|WO_IS, 0);
if( pAlt==0 ) continue;
if( pAlt->wtFlags & (TERM_CODED) ) continue;
if( (pAlt->eOperator & WO_IN)
- && (pAlt->pExpr->flags & EP_xIsSelect)
+ && ExprUseXSelect(pAlt->pExpr)
&& (pAlt->pExpr->x.pSelect->pEList->nExpr>1)
){
continue;
@@ -149412,6 +157337,48 @@ SQLITE_PRIVATE Bitmask sqlcipher_sqlite3WhereCodeOneLoopStart(
sEAlt = *pAlt->pExpr;
sEAlt.pLeft = pE->pLeft;
sqlcipher_sqlite3ExprIfFalse(pParse, &sEAlt, addrCont, SQLITE_JUMPIFNULL);
+ pAlt->wtFlags |= TERM_CODED;
+ }
+
+ /* For a RIGHT OUTER JOIN, record the fact that the current row has
+ ** been matched at least once.
+ */
+ if( pLevel->pRJ ){
+ Table *pTab;
+ int nPk;
+ int r;
+ int jmp1 = 0;
+ WhereRightJoin *pRJ = pLevel->pRJ;
+
+ /* pTab is the right-hand table of the RIGHT JOIN. Generate code that
+ ** will record that the current row of that table has been matched at
+ ** least once. This is accomplished by storing the PK for the row in
+ ** both the iMatch index and the regBloom Bloom filter.
+ */
+ pTab = pWInfo->pTabList->a[pLevel->iFrom].pTab;
+ if( HasRowid(pTab) ){
+ r = sqlcipher_sqlite3GetTempRange(pParse, 2);
+ sqlcipher_sqlite3ExprCodeGetColumnOfTable(v, pTab, pLevel->iTabCur, -1, r+1);
+ nPk = 1;
+ }else{
+ int iPk;
+ Index *pPk = sqlcipher_sqlite3PrimaryKeyIndex(pTab);
+ nPk = pPk->nKeyCol;
+ r = sqlcipher_sqlite3GetTempRange(pParse, nPk+1);
+ for(iPk=0; iPk<nPk; iPk++){
+ int iCol = pPk->aiColumn[iPk];
+ sqlcipher_sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, iCol,r+1+iPk);
+ }
+ }
+ jmp1 = sqlcipher_sqlite3VdbeAddOp4Int(v, OP_Found, pRJ->iMatch, 0, r+1, nPk);
+ VdbeCoverage(v);
+ VdbeComment((v, "match against %s", pTab->zName));
+ sqlcipher_sqlite3VdbeAddOp3(v, OP_MakeRecord, r+1, nPk, r);
+ sqlcipher_sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pRJ->iMatch, r, r+1, nPk);
+ sqlcipher_sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pRJ->regBloom, 0, r+1, nPk);
+ sqlcipher_sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
+ sqlcipher_sqlite3VdbeJumpHere(v, jmp1);
+ sqlcipher_sqlite3ReleaseTempRange(pParse, r, nPk+1);
}
/* For a LEFT OUTER JOIN, generate code that will record the fact that
@@ -149421,7 +157388,31 @@ SQLITE_PRIVATE Bitmask sqlcipher_sqlite3WhereCodeOneLoopStart(
pLevel->addrFirst = sqlcipher_sqlite3VdbeCurrentAddr(v);
sqlcipher_sqlite3VdbeAddOp2(v, OP_Integer, 1, pLevel->iLeftJoin);
VdbeComment((v, "record LEFT JOIN hit"));
- for(pTerm=pWC->a, j=0; j<pWC->nTerm; j++, pTerm++){
+ if( pLevel->pRJ==0 ){
+ goto code_outer_join_constraints; /* WHERE clause constraints */
+ }
+ }
+
+ if( pLevel->pRJ ){
+ /* Create a subroutine used to process all interior loops and code
+ ** of the RIGHT JOIN. During normal operation, the subroutine will
+ ** be in-line with the rest of the code. But at the end, a separate
+ ** loop will run that invokes this subroutine for unmatched rows
+ ** of pTab, with all tables to left begin set to NULL.
+ */
+ WhereRightJoin *pRJ = pLevel->pRJ;
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_BeginSubrtn, 0, pRJ->regReturn);
+ pRJ->addrSubrtn = sqlcipher_sqlite3VdbeCurrentAddr(v);
+ assert( pParse->withinRJSubrtn < 255 );
+ pParse->withinRJSubrtn++;
+
+ /* WHERE clause constraints must be deferred until after outer join
+ ** row elimination has completed, since WHERE clause constraints apply
+ ** to the results of the OUTER JOIN. The following loop generates the
+ ** appropriate WHERE clause constraint checks. tag-20220513a.
+ */
+ code_outer_join_constraints:
+ for(pTerm=pWC->a, j=0; j<pWC->nBase; j++, pTerm++){
testcase( pTerm->wtFlags & TERM_VIRTUAL );
testcase( pTerm->wtFlags & TERM_CODED );
if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
@@ -149429,6 +157420,7 @@ SQLITE_PRIVATE Bitmask sqlcipher_sqlite3WhereCodeOneLoopStart(
assert( pWInfo->untestedTerms );
continue;
}
+ if( pTabItem->fg.jointype & JT_LTORJ ) continue;
assert( pTerm->pExpr );
sqlcipher_sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL);
pTerm->wtFlags |= TERM_CODED;
@@ -149449,6 +157441,96 @@ SQLITE_PRIVATE Bitmask sqlcipher_sqlite3WhereCodeOneLoopStart(
return pLevel->notReady;
}
+/*
+** Generate the code for the loop that finds all non-matched terms
+** for a RIGHT JOIN.
+*/
+SQLITE_PRIVATE SQLITE_NOINLINE void sqlcipher_sqlite3WhereRightJoinLoop(
+ WhereInfo *pWInfo,
+ int iLevel,
+ WhereLevel *pLevel
+){
+ Parse *pParse = pWInfo->pParse;
+ Vdbe *v = pParse->pVdbe;
+ WhereRightJoin *pRJ = pLevel->pRJ;
+ Expr *pSubWhere = 0;
+ WhereClause *pWC = &pWInfo->sWC;
+ WhereInfo *pSubWInfo;
+ WhereLoop *pLoop = pLevel->pWLoop;
+ SrcItem *pTabItem = &pWInfo->pTabList->a[pLevel->iFrom];
+ SrcList sFrom;
+ Bitmask mAll = 0;
+ int k;
+
+ ExplainQueryPlan((pParse, 1, "RIGHT-JOIN %s", pTabItem->pTab->zName));
+ sqlcipher_sqlite3VdbeNoJumpsOutsideSubrtn(v, pRJ->addrSubrtn, pRJ->endSubrtn,
+ pRJ->regReturn);
+ for(k=0; k<iLevel; k++){
+ int iIdxCur;
+ mAll |= pWInfo->a[k].pWLoop->maskSelf;
+ sqlcipher_sqlite3VdbeAddOp1(v, OP_NullRow, pWInfo->a[k].iTabCur);
+ iIdxCur = pWInfo->a[k].iIdxCur;
+ if( iIdxCur ){
+ sqlcipher_sqlite3VdbeAddOp1(v, OP_NullRow, iIdxCur);
+ }
+ }
+ if( (pTabItem->fg.jointype & JT_LTORJ)==0 ){
+ mAll |= pLoop->maskSelf;
+ for(k=0; k<pWC->nTerm; k++){
+ WhereTerm *pTerm = &pWC->a[k];
+ if( (pTerm->wtFlags & (TERM_VIRTUAL|TERM_SLICE))!=0
+ && pTerm->eOperator!=WO_ROWVAL
+ ){
+ break;
+ }
+ if( pTerm->prereqAll & ~mAll ) continue;
+ if( ExprHasProperty(pTerm->pExpr, EP_OuterON|EP_InnerON) ) continue;
+ pSubWhere = sqlcipher_sqlite3ExprAnd(pParse, pSubWhere,
+ sqlcipher_sqlite3ExprDup(pParse->db, pTerm->pExpr, 0));
+ }
+ }
+ sFrom.nSrc = 1;
+ sFrom.nAlloc = 1;
+ memcpy(&sFrom.a[0], pTabItem, sizeof(SrcItem));
+ sFrom.a[0].fg.jointype = 0;
+ assert( pParse->withinRJSubrtn < 100 );
+ pParse->withinRJSubrtn++;
+ pSubWInfo = sqlcipher_sqlite3WhereBegin(pParse, &sFrom, pSubWhere, 0, 0, 0,
+ WHERE_RIGHT_JOIN, 0);
+ if( pSubWInfo ){
+ int iCur = pLevel->iTabCur;
+ int r = ++pParse->nMem;
+ int nPk;
+ int jmp;
+ int addrCont = sqlcipher_sqlite3WhereContinueLabel(pSubWInfo);
+ Table *pTab = pTabItem->pTab;
+ if( HasRowid(pTab) ){
+ sqlcipher_sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, -1, r);
+ nPk = 1;
+ }else{
+ int iPk;
+ Index *pPk = sqlcipher_sqlite3PrimaryKeyIndex(pTab);
+ nPk = pPk->nKeyCol;
+ pParse->nMem += nPk - 1;
+ for(iPk=0; iPk<nPk; iPk++){
+ int iCol = pPk->aiColumn[iPk];
+ sqlcipher_sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, iCol,r+iPk);
+ }
+ }
+ jmp = sqlcipher_sqlite3VdbeAddOp4Int(v, OP_Filter, pRJ->regBloom, 0, r, nPk);
+ VdbeCoverage(v);
+ sqlcipher_sqlite3VdbeAddOp4Int(v, OP_Found, pRJ->iMatch, addrCont, r, nPk);
+ VdbeCoverage(v);
+ sqlcipher_sqlite3VdbeJumpHere(v, jmp);
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_Gosub, pRJ->regReturn, pRJ->addrSubrtn);
+ sqlcipher_sqlite3WhereEnd(pSubWInfo);
+ }
+ sqlcipher_sqlite3ExprDelete(pParse->db, pSubWhere);
+ ExplainQueryPlanPop(pParse);
+ assert( pParse->withinRJSubrtn>0 );
+ pParse->withinRJSubrtn--;
+}
+
/************** End of wherecode.c *******************************************/
/************** Begin file whereexpr.c ***************************************/
/*
@@ -149517,7 +157599,7 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u16 wtFlags){
if( pWC->nTerm>=pWC->nSlot ){
WhereTerm *pOld = pWC->a;
sqlcipher_sqlite3 *db = pWC->pWInfo->pParse->db;
- pWC->a = sqlcipher_sqlite3DbMallocRawNN(db, sizeof(pWC->a[0])*pWC->nSlot*2 );
+ pWC->a = sqlcipher_sqlite3WhereMalloc(pWC->pWInfo, sizeof(pWC->a[0])*pWC->nSlot*2 );
if( pWC->a==0 ){
if( wtFlags & TERM_DYNAMIC ){
sqlcipher_sqlite3ExprDelete(db, p);
@@ -149526,12 +157608,10 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u16 wtFlags){
return 0;
}
memcpy(pWC->a, pOld, sizeof(pWC->a[0])*pWC->nTerm);
- if( pOld!=pWC->aStatic ){
- sqlcipher_sqlite3DbFree(db, pOld);
- }
- pWC->nSlot = sqlcipher_sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]);
+ pWC->nSlot = pWC->nSlot*2;
}
pTerm = &pWC->a[idx = pWC->nTerm++];
+ if( (wtFlags & TERM_VIRTUAL)==0 ) pWC->nBase = pWC->nTerm;
if( p && ExprHasProperty(p, EP_Unlikely) ){
pTerm->truthProb = sqlcipher_sqlite3LogEst(p->iTable) - 270;
}else{
@@ -149648,6 +157728,7 @@ static int isLikeOrGlob(
#ifdef SQLITE_EBCDIC
if( *pnoCase ) return 0;
#endif
+ assert( ExprUseXList(pExpr) );
pList = pExpr->x.pList;
pLeft = pList->a[1].pExpr;
@@ -149663,7 +157744,8 @@ static int isLikeOrGlob(
sqlcipher_sqlite3VdbeSetVarmask(pParse->pVdbe, iCol);
assert( pRight->op==TK_VARIABLE || pRight->op==TK_REGISTER );
}else if( op==TK_STRING ){
- z = (u8*)pRight->u.zToken;
+ assert( !ExprHasProperty(pRight, EP_IntValue) );
+ z = (u8*)pRight->u.zToken;
}
if( z ){
@@ -149692,7 +157774,9 @@ static int isLikeOrGlob(
pPrefix = sqlcipher_sqlite3Expr(db, TK_STRING, (char*)z);
if( pPrefix ){
int iFrom, iTo;
- char *zNew = pPrefix->u.zToken;
+ char *zNew;
+ assert( !ExprHasProperty(pPrefix, EP_IntValue) );
+ zNew = pPrefix->u.zToken;
zNew[cnt] = 0;
for(iFrom=iTo=0; iFrom<cnt; iFrom++){
if( zNew[iFrom]==wc[3] ) iFrom++;
@@ -149716,7 +157800,9 @@ static int isLikeOrGlob(
*/
if( pLeft->op!=TK_COLUMN
|| sqlcipher_sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT
- || IsVirtual(pLeft->y.pTab) /* Value might be numeric */
+ || (ALWAYS( ExprUseYTab(pLeft) )
+ && pLeft->y.pTab
+ && IsVirtual(pLeft->y.pTab)) /* Might be numeric */
){
int isNum;
double rDummy;
@@ -149744,6 +157830,7 @@ static int isLikeOrGlob(
if( op==TK_VARIABLE ){
Vdbe *v = pParse->pVdbe;
sqlcipher_sqlite3VdbeSetVarmask(v, pRight->iColumn);
+ assert( !ExprHasProperty(pRight, EP_IntValue) );
if( *pisComplete && pRight->u.zToken[1] ){
/* If the rhs of the LIKE expression is a variable, and the current
** value of the variable means there is no need to invoke the LIKE
@@ -149817,6 +157904,7 @@ static int isAuxiliaryVtabOperator(
Expr *pCol; /* Column reference */
int i;
+ assert( ExprUseXList(pExpr) );
pList = pExpr->x.pList;
if( pList==0 || pList->nExpr!=2 ){
return 0;
@@ -149830,9 +157918,11 @@ static int isAuxiliaryVtabOperator(
** MATCH(expression,vtab_column)
*/
pCol = pList->a[1].pExpr;
+ assert( pCol->op!=TK_COLUMN || ExprUseYTab(pCol) );
testcase( pCol->op==TK_COLUMN && pCol->y.pTab==0 );
if( ExprIsVtab(pCol) ){
for(i=0; i<ArraySize(aOp); i++){
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
if( sqlcipher_sqlite3StrICmp(pExpr->u.zToken, aOp[i].zOp)==0 ){
*peOp2 = aOp[i].eOp2;
*ppRight = pList->a[0].pExpr;
@@ -149853,6 +157943,7 @@ static int isAuxiliaryVtabOperator(
** with function names in an arbitrary case.
*/
pCol = pList->a[0].pExpr;
+ assert( pCol->op!=TK_COLUMN || ExprUseYTab(pCol) );
testcase( pCol->op==TK_COLUMN && pCol->y.pTab==0 );
if( ExprIsVtab(pCol) ){
sqlcipher_sqlite3_vtab *pVtab;
@@ -149862,6 +157953,7 @@ static int isAuxiliaryVtabOperator(
pVtab = sqlcipher_sqlite3GetVTable(db, pCol->y.pTab)->pVtab;
assert( pVtab!=0 );
assert( pVtab->pModule!=0 );
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
pMod = (sqlcipher_sqlite3_module *)pVtab->pModule;
if( pMod->xFindFunction!=0 ){
i = pMod->xFindFunction(pVtab,2, pExpr->u.zToken, &xNotUsed, &pNotUsed);
@@ -149877,10 +157969,12 @@ static int isAuxiliaryVtabOperator(
int res = 0;
Expr *pLeft = pExpr->pLeft;
Expr *pRight = pExpr->pRight;
+ assert( pLeft->op!=TK_COLUMN || ExprUseYTab(pLeft) );
testcase( pLeft->op==TK_COLUMN && pLeft->y.pTab==0 );
if( ExprIsVtab(pLeft) ){
res++;
}
+ assert( pRight==0 || pRight->op!=TK_COLUMN || ExprUseYTab(pRight) );
testcase( pRight && pRight->op==TK_COLUMN && pRight->y.pTab==0 );
if( pRight && ExprIsVtab(pRight) ){
res++;
@@ -149902,9 +157996,9 @@ static int isAuxiliaryVtabOperator(
** a join, then transfer the appropriate markings over to derived.
*/
static void transferJoinMarkings(Expr *pDerived, Expr *pBase){
- if( pDerived ){
- pDerived->flags |= pBase->flags & EP_FromJoin;
- pDerived->iRightJoinTable = pBase->iRightJoinTable;
+ if( pDerived && ExprHasProperty(pBase, EP_OuterON|EP_InnerON) ){
+ pDerived->flags |= pBase->flags & (EP_OuterON|EP_InnerON);
+ pDerived->w.iJoin = pBase->w.iJoin;
}
}
@@ -149964,6 +158058,7 @@ static void whereCombineDisjuncts(
int op; /* Operator for the combined expression */
int idxNew; /* Index in pWC of the next virtual term */
+ if( (pOne->wtFlags | pTwo->wtFlags) & TERM_VNULL ) return;
if( (pOne->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return;
if( (pTwo->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return;
if( (eOp & (WO_EQ|WO_LT|WO_LE))!=eOp
@@ -150132,6 +158227,7 @@ static void exprAnalyzeOrTerm(
pOrTerm->u.pAndInfo = pAndInfo;
pOrTerm->wtFlags |= TERM_ANDINFO;
pOrTerm->eOperator = WO_AND;
+ pOrTerm->leftCursor = -1;
pAndWC = &pAndInfo->wc;
memset(pAndWC->aStatic, 0, sizeof(pAndWC->aStatic));
sqlcipher_sqlite3WhereClauseInit(pAndWC, pWC->pWInfo);
@@ -150174,11 +158270,10 @@ static void exprAnalyzeOrTerm(
** empty.
*/
pOrInfo->indexable = indexable;
+ pTerm->eOperator = WO_OR;
+ pTerm->leftCursor = -1;
if( indexable ){
- pTerm->eOperator = WO_OR;
pWC->hasOr = 1;
- }else{
- pTerm->eOperator = WO_OR;
}
/* For a two-way OR, attempt to implementation case 2.
@@ -150233,7 +158328,7 @@ static void exprAnalyzeOrTerm(
pOrTerm = pOrWc->a;
for(i=pOrWc->nTerm-1; i>=0; i--, pOrTerm++){
assert( pOrTerm->eOperator & WO_EQ );
- pOrTerm->wtFlags &= ~TERM_OR_OK;
+ pOrTerm->wtFlags &= ~TERM_OK;
if( pOrTerm->leftCursor==iCursor ){
/* This is the 2-bit case and we are on the second iteration and
** current term is from the first iteration. So skip this term. */
@@ -150251,6 +158346,7 @@ static void exprAnalyzeOrTerm(
assert( pOrTerm->wtFlags & (TERM_COPIED|TERM_VIRTUAL) );
continue;
}
+ assert( (pOrTerm->eOperator & (WO_OR|WO_AND))==0 );
iColumn = pOrTerm->u.x.leftColumn;
iCursor = pOrTerm->leftCursor;
pLeft = pOrTerm->pExpr->pLeft;
@@ -150271,8 +158367,9 @@ static void exprAnalyzeOrTerm(
okToChngToIN = 1;
for(; i>=0 && okToChngToIN; i--, pOrTerm++){
assert( pOrTerm->eOperator & WO_EQ );
+ assert( (pOrTerm->eOperator & (WO_OR|WO_AND))==0 );
if( pOrTerm->leftCursor!=iCursor ){
- pOrTerm->wtFlags &= ~TERM_OR_OK;
+ pOrTerm->wtFlags &= ~TERM_OK;
}else if( pOrTerm->u.x.leftColumn!=iColumn || (iColumn==XN_EXPR
&& sqlcipher_sqlite3ExprCompare(pParse, pOrTerm->pExpr->pLeft, pLeft, -1)
)){
@@ -150288,7 +158385,7 @@ static void exprAnalyzeOrTerm(
if( affRight!=0 && affRight!=affLeft ){
okToChngToIN = 0;
}else{
- pOrTerm->wtFlags |= TERM_OR_OK;
+ pOrTerm->wtFlags |= TERM_OK;
}
}
}
@@ -150305,8 +158402,9 @@ static void exprAnalyzeOrTerm(
Expr *pNew; /* The complete IN operator */
for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0; i--, pOrTerm++){
- if( (pOrTerm->wtFlags & TERM_OR_OK)==0 ) continue;
+ if( (pOrTerm->wtFlags & TERM_OK)==0 ) continue;
assert( pOrTerm->eOperator & WO_EQ );
+ assert( (pOrTerm->eOperator & (WO_OR|WO_AND))==0 );
assert( pOrTerm->leftCursor==iCursor );
assert( pOrTerm->u.x.leftColumn==iColumn );
pDup = sqlcipher_sqlite3ExprDup(db, pOrTerm->pExpr->pRight, 0);
@@ -150319,12 +158417,12 @@ static void exprAnalyzeOrTerm(
if( pNew ){
int idxNew;
transferJoinMarkings(pNew, pExpr);
- assert( !ExprHasProperty(pNew, EP_xIsSelect) );
+ assert( ExprUseXList(pNew) );
pNew->x.pList = pList;
idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC);
testcase( idxNew==0 );
exprAnalyze(pSrc, pWC, idxNew);
- /* pTerm = &pWC->a[idxTerm]; // would be needed if pTerm where used again */
+ /* pTerm = &pWC->a[idxTerm]; // would be needed if pTerm where reused */
markTermAsChild(pWC, idxNew, idxTerm);
}else{
sqlcipher_sqlite3ExprListDelete(db, pList);
@@ -150354,7 +158452,7 @@ static int termIsEquivalence(Parse *pParse, Expr *pExpr){
CollSeq *pColl;
if( !OptimizationEnabled(pParse->db, SQLITE_Transitive) ) return 0;
if( pExpr->op!=TK_EQ && pExpr->op!=TK_IS ) return 0;
- if( ExprHasProperty(pExpr, EP_FromJoin) ) return 0;
+ if( ExprHasProperty(pExpr, EP_OuterON) ) return 0;
aff1 = sqlcipher_sqlite3ExprAffinity(pExpr->pLeft);
aff2 = sqlcipher_sqlite3ExprAffinity(pExpr->pRight);
if( aff1!=aff2
@@ -150385,7 +158483,9 @@ static Bitmask exprSelectUsage(WhereMaskSet *pMaskSet, Select *pS){
int i;
for(i=0; i<pSrc->nSrc; i++){
mask |= exprSelectUsage(pMaskSet, pSrc->a[i].pSelect);
- mask |= sqlcipher_sqlite3WhereExprUsage(pMaskSet, pSrc->a[i].pOn);
+ if( pSrc->a[i].fg.isUsing==0 ){
+ mask |= sqlcipher_sqlite3WhereExprUsage(pMaskSet, pSrc->a[i].u3.pOn);
+ }
if( pSrc->a[i].fg.isTabFunc ){
mask |= sqlcipher_sqlite3WhereExprListUsage(pMaskSet, pSrc->a[i].u1.pFuncArg);
}
@@ -150447,7 +158547,9 @@ static int exprMightBeIndexed(
assert( TK_IS<TK_GE && TK_ISNULL<TK_GE && TK_IN<TK_GE );
assert( op<=TK_GE );
if( pExpr->op==TK_VECTOR && (op>=TK_GT && ALWAYS(op<=TK_GE)) ){
+ assert( ExprUseXList(pExpr) );
pExpr = pExpr->x.pList->a[0].pExpr;
+
}
if( pExpr->op==TK_COLUMN ){
@@ -150460,6 +158562,7 @@ static int exprMightBeIndexed(
return exprMightBeIndexed2(pFrom,mPrereq,aiCurCol,pExpr);
}
+
/*
** The input to this routine is an WhereTerm structure with only the
** "pExpr" field filled in. The job of this routine is to analyze the
@@ -150502,36 +158605,67 @@ static void exprAnalyze(
if( db->mallocFailed ){
return;
}
+ assert( pWC->nTerm > idxTerm );
pTerm = &pWC->a[idxTerm];
pMaskSet = &pWInfo->sMaskSet;
pExpr = pTerm->pExpr;
+ assert( pExpr!=0 ); /* Because malloc() has not failed */
assert( pExpr->op!=TK_AS && pExpr->op!=TK_COLLATE );
+ pMaskSet->bVarSelect = 0;
prereqLeft = sqlcipher_sqlite3WhereExprUsage(pMaskSet, pExpr->pLeft);
op = pExpr->op;
if( op==TK_IN ){
assert( pExpr->pRight==0 );
if( sqlcipher_sqlite3ExprCheckIN(pParse, pExpr) ) return;
- if( ExprHasProperty(pExpr, EP_xIsSelect) ){
+ if( ExprUseXSelect(pExpr) ){
pTerm->prereqRight = exprSelectUsage(pMaskSet, pExpr->x.pSelect);
}else{
pTerm->prereqRight = sqlcipher_sqlite3WhereExprListUsage(pMaskSet, pExpr->x.pList);
}
- }else if( op==TK_ISNULL ){
- pTerm->prereqRight = 0;
+ prereqAll = prereqLeft | pTerm->prereqRight;
}else{
pTerm->prereqRight = sqlcipher_sqlite3WhereExprUsage(pMaskSet, pExpr->pRight);
+ if( pExpr->pLeft==0
+ || ExprHasProperty(pExpr, EP_xIsSelect|EP_IfNullRow)
+ || pExpr->x.pList!=0
+ ){
+ prereqAll = sqlcipher_sqlite3WhereExprUsageNN(pMaskSet, pExpr);
+ }else{
+ prereqAll = prereqLeft | pTerm->prereqRight;
+ }
}
- pMaskSet->bVarSelect = 0;
- prereqAll = sqlcipher_sqlite3WhereExprUsageNN(pMaskSet, pExpr);
if( pMaskSet->bVarSelect ) pTerm->wtFlags |= TERM_VARSELECT;
- if( ExprHasProperty(pExpr, EP_FromJoin) ){
- Bitmask x = sqlcipher_sqlite3WhereGetMask(pMaskSet, pExpr->iRightJoinTable);
- prereqAll |= x;
- extraRight = x-1; /* ON clause terms may not be used with an index
- ** on left table of a LEFT JOIN. Ticket #3015 */
- if( (prereqAll>>1)>=x ){
- sqlcipher_sqlite3ErrorMsg(pParse, "ON clause references tables to its right");
- return;
+
+#ifdef SQLITE_DEBUG
+ if( prereqAll!=sqlcipher_sqlite3WhereExprUsageNN(pMaskSet, pExpr) ){
+ printf("\n*** Incorrect prereqAll computed for:\n");
+ sqlcipher_sqlite3TreeViewExpr(0,pExpr,0);
+ assert( 0 );
+ }
+#endif
+
+ if( ExprHasProperty(pExpr, EP_OuterON|EP_InnerON) ){
+ Bitmask x = sqlcipher_sqlite3WhereGetMask(pMaskSet, pExpr->w.iJoin);
+ if( ExprHasProperty(pExpr, EP_OuterON) ){
+ prereqAll |= x;
+ extraRight = x-1; /* ON clause terms may not be used with an index
+ ** on left table of a LEFT JOIN. Ticket #3015 */
+ if( (prereqAll>>1)>=x ){
+ sqlcipher_sqlite3ErrorMsg(pParse, "ON clause references tables to its right");
+ return;
+ }
+ }else if( (prereqAll>>1)>=x ){
+ /* The ON clause of an INNER JOIN references a table to its right.
+ ** Most other SQL database engines raise an error. But SQLite versions
+ ** 3.0 through 3.38 just put the ON clause constraint into the WHERE
+ ** clause and carried on. Beginning with 3.39, raise an error only
+ ** if there is a RIGHT or FULL JOIN in the query. This makes SQLite
+ ** more like other systems, and also preserves legacy. */
+ if( ALWAYS(pSrc->nSrc>0) && (pSrc->a[0].fg.jointype & JT_LTORJ)!=0 ){
+ sqlcipher_sqlite3ErrorMsg(pParse, "ON clause references tables to its right");
+ return;
+ }
+ ExprClearProperty(pExpr, EP_InnerON);
}
}
pTerm->prereqAll = prereqAll;
@@ -150547,17 +158681,20 @@ static void exprAnalyze(
if( pTerm->u.x.iField>0 ){
assert( op==TK_IN );
assert( pLeft->op==TK_VECTOR );
+ assert( ExprUseXList(pLeft) );
pLeft = pLeft->x.pList->a[pTerm->u.x.iField-1].pExpr;
}
if( exprMightBeIndexed(pSrc, prereqLeft, aiCurCol, pLeft, op) ){
pTerm->leftCursor = aiCurCol[0];
+ assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
pTerm->u.x.leftColumn = aiCurCol[1];
pTerm->eOperator = operatorMask(op) & opMask;
}
if( op==TK_IS ) pTerm->wtFlags |= TERM_IS;
if( pRight
&& exprMightBeIndexed(pSrc, pTerm->prereqRight, aiCurCol, pRight, op)
+ && !ExprHasProperty(pRight, EP_FixedCol)
){
WhereTerm *pNew;
Expr *pDup;
@@ -150588,11 +158725,23 @@ static void exprAnalyze(
}
pNew->wtFlags |= exprCommute(pParse, pDup);
pNew->leftCursor = aiCurCol[0];
+ assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
pNew->u.x.leftColumn = aiCurCol[1];
testcase( (prereqLeft | extraRight) != prereqLeft );
pNew->prereqRight = prereqLeft | extraRight;
pNew->prereqAll = prereqAll;
pNew->eOperator = (operatorMask(pDup->op) + eExtraOp) & opMask;
+ }else
+ if( op==TK_ISNULL
+ && !ExprHasProperty(pExpr,EP_OuterON)
+ && 0==sqlcipher_sqlite3ExprCanBeNull(pLeft)
+ ){
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
+ pExpr->op = TK_TRUEFALSE;
+ pExpr->u.zToken = "false";
+ ExprSetProperty(pExpr, EP_IsFalse);
+ pTerm->prereqAll = 0;
+ pTerm->eOperator = 0;
}
}
@@ -150613,9 +158762,11 @@ static void exprAnalyze(
** BETWEEN term is skipped.
*/
else if( pExpr->op==TK_BETWEEN && pWC->op==TK_AND ){
- ExprList *pList = pExpr->x.pList;
+ ExprList *pList;
int i;
static const u8 ops[] = {TK_GE, TK_LE};
+ assert( ExprUseXList(pExpr) );
+ pList = pExpr->x.pList;
assert( pList!=0 );
assert( pList->nExpr==2 );
for(i=0; i<2; i++){
@@ -150644,6 +158795,42 @@ static void exprAnalyze(
pTerm = &pWC->a[idxTerm];
}
#endif /* SQLITE_OMIT_OR_OPTIMIZATION */
+ /* 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
+ ** virtual term of that form.
+ **
+ ** The virtual term must be tagged with TERM_VNULL.
+ */
+ else if( pExpr->op==TK_NOTNULL ){
+ if( pExpr->pLeft->op==TK_COLUMN
+ && pExpr->pLeft->iColumn>=0
+ && !ExprHasProperty(pExpr, EP_OuterON)
+ ){
+ Expr *pNewExpr;
+ Expr *pLeft = pExpr->pLeft;
+ int idxNew;
+ WhereTerm *pNewTerm;
+
+ pNewExpr = sqlcipher_sqlite3PExpr(pParse, TK_GT,
+ sqlcipher_sqlite3ExprDup(db, pLeft, 0),
+ sqlcipher_sqlite3ExprAlloc(db, TK_NULL, 0, 0));
+
+ idxNew = whereClauseInsert(pWC, pNewExpr,
+ TERM_VIRTUAL|TERM_DYNAMIC|TERM_VNULL);
+ if( idxNew ){
+ pNewTerm = &pWC->a[idxNew];
+ pNewTerm->prereqRight = 0;
+ pNewTerm->leftCursor = pLeft->iTable;
+ pNewTerm->u.x.leftColumn = pLeft->iColumn;
+ pNewTerm->eOperator = WO_GT;
+ markTermAsChild(pWC, idxNew, idxTerm);
+ pTerm = &pWC->a[idxTerm];
+ pTerm->wtFlags |= TERM_COPIED;
+ pNewTerm->prereqAll = pTerm->prereqAll;
+ }
+ }
+ }
+
#ifndef SQLITE_OMIT_LIKE_OPTIMIZATION
/* Add constraints to reduce the search space on a LIKE or GLOB
@@ -150659,7 +158846,8 @@ static void exprAnalyze(
** bound is made all lowercase so that the bounds also work when comparing
** BLOBs.
*/
- if( pWC->op==TK_AND
+ else if( pExpr->op==TK_FUNCTION
+ && pWC->op==TK_AND
&& isLikeOrGlob(pParse, pExpr, &pStr1, &isComplete, &noCase)
){
Expr *pLeft; /* LHS of LIKE/GLOB operator */
@@ -150671,8 +158859,12 @@ static void exprAnalyze(
const char *zCollSeqName; /* Name of collating sequence */
const u16 wtFlags = TERM_LIKEOPT | TERM_VIRTUAL | TERM_DYNAMIC;
+ assert( ExprUseXList(pExpr) );
pLeft = pExpr->x.pList->a[1].pExpr;
pStr2 = sqlcipher_sqlite3ExprDup(db, pStr1, 0);
+ assert( pStr1==0 || !ExprHasProperty(pStr1, EP_IntValue) );
+ assert( pStr2==0 || !ExprHasProperty(pStr2, EP_IntValue) );
+
/* Convert the lower bound to upper-case and the upper bound to
** lower-case (upper-case is less than lower-case in ASCII) so that
@@ -150729,81 +158921,38 @@ static void exprAnalyze(
}
#endif /* SQLITE_OMIT_LIKE_OPTIMIZATION */
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- /* Add a WO_AUX auxiliary term to the constraint set if the
- ** current expression is of the form "column OP expr" where OP
- ** is an operator that gets passed into virtual tables but which is
- ** not normally optimized for ordinary tables. In other words, OP
- ** is one of MATCH, LIKE, GLOB, REGEXP, !=, IS, IS NOT, or NOT NULL.
- ** This information is used by the xBestIndex methods of
- ** virtual tables. The native query optimizer does not attempt
- ** to do anything with MATCH functions.
- */
- if( pWC->op==TK_AND ){
- Expr *pRight = 0, *pLeft = 0;
- int res = isAuxiliaryVtabOperator(db, pExpr, &eOp2, &pLeft, &pRight);
- while( res-- > 0 ){
- int idxNew;
- WhereTerm *pNewTerm;
- Bitmask prereqColumn, prereqExpr;
-
- prereqExpr = sqlcipher_sqlite3WhereExprUsage(pMaskSet, pRight);
- prereqColumn = sqlcipher_sqlite3WhereExprUsage(pMaskSet, pLeft);
- if( (prereqExpr & prereqColumn)==0 ){
- Expr *pNewExpr;
- pNewExpr = sqlcipher_sqlite3PExpr(pParse, TK_MATCH,
- 0, sqlcipher_sqlite3ExprDup(db, pRight, 0));
- if( ExprHasProperty(pExpr, EP_FromJoin) && pNewExpr ){
- ExprSetProperty(pNewExpr, EP_FromJoin);
- pNewExpr->iRightJoinTable = pExpr->iRightJoinTable;
- }
- idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
- testcase( idxNew==0 );
- pNewTerm = &pWC->a[idxNew];
- pNewTerm->prereqRight = prereqExpr;
- pNewTerm->leftCursor = pLeft->iTable;
- pNewTerm->u.x.leftColumn = pLeft->iColumn;
- pNewTerm->eOperator = WO_AUX;
- pNewTerm->eMatchOp = eOp2;
- markTermAsChild(pWC, idxNew, idxTerm);
- pTerm = &pWC->a[idxTerm];
- pTerm->wtFlags |= TERM_COPIED;
- pNewTerm->prereqAll = pTerm->prereqAll;
- }
- SWAP(Expr*, pLeft, pRight);
- }
- }
-#endif /* SQLITE_OMIT_VIRTUALTABLE */
-
/* If there is a vector == or IS term - e.g. "(a, b) == (?, ?)" - create
** new terms for each component comparison - "a = ?" and "b = ?". The
** new terms completely replace the original vector comparison, which is
** no longer used.
**
** This is only required if at least one side of the comparison operation
- ** is not a sub-select. */
- if( pWC->op==TK_AND
- && (pExpr->op==TK_EQ || pExpr->op==TK_IS)
- && (nLeft = sqlcipher_sqlite3ExprVectorSize(pExpr->pLeft))>1
- && sqlcipher_sqlite3ExprVectorSize(pExpr->pRight)==nLeft
- && ( (pExpr->pLeft->flags & EP_xIsSelect)==0
- || (pExpr->pRight->flags & EP_xIsSelect)==0)
+ ** is not a sub-select.
+ **
+ ** tag-20220128a
+ */
+ if( (pExpr->op==TK_EQ || pExpr->op==TK_IS)
+ && (nLeft = sqlcipher_sqlite3ExprVectorSize(pExpr->pLeft))>1
+ && sqlcipher_sqlite3ExprVectorSize(pExpr->pRight)==nLeft
+ && ( (pExpr->pLeft->flags & EP_xIsSelect)==0
+ || (pExpr->pRight->flags & EP_xIsSelect)==0)
+ && pWC->op==TK_AND
){
int i;
for(i=0; i<nLeft; i++){
int idxNew;
Expr *pNew;
- Expr *pLeft = sqlcipher_sqlite3ExprForVectorField(pParse, pExpr->pLeft, i);
- Expr *pRight = sqlcipher_sqlite3ExprForVectorField(pParse, pExpr->pRight, i);
+ Expr *pLeft = sqlcipher_sqlite3ExprForVectorField(pParse, pExpr->pLeft, i, nLeft);
+ Expr *pRight = sqlcipher_sqlite3ExprForVectorField(pParse, pExpr->pRight, i, nLeft);
pNew = sqlcipher_sqlite3PExpr(pParse, pExpr->op, pLeft, pRight);
transferJoinMarkings(pNew, pExpr);
- idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC);
+ idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC|TERM_SLICE);
exprAnalyze(pSrc, pWC, idxNew);
}
pTerm = &pWC->a[idxTerm];
pTerm->wtFlags |= TERM_CODED|TERM_VIRTUAL; /* Disable the original */
- pTerm->eOperator = 0;
+ pTerm->eOperator = WO_ROWVAL;
}
/* If there is a vector IN term - e.g. "(a, b) IN (SELECT ...)" - create
@@ -150815,61 +158964,71 @@ static void exprAnalyze(
** This only works if the RHS is a simple SELECT (not a compound) that does
** not use window functions.
*/
- if( pWC->op==TK_AND && pExpr->op==TK_IN && pTerm->u.x.iField==0
+ else if( pExpr->op==TK_IN
+ && pTerm->u.x.iField==0
&& pExpr->pLeft->op==TK_VECTOR
+ && ALWAYS( ExprUseXSelect(pExpr) )
&& pExpr->x.pSelect->pPrior==0
#ifndef SQLITE_OMIT_WINDOWFUNC
&& pExpr->x.pSelect->pWin==0
#endif
+ && pWC->op==TK_AND
){
int i;
for(i=0; i<sqlcipher_sqlite3ExprVectorSize(pExpr->pLeft); i++){
int idxNew;
- idxNew = whereClauseInsert(pWC, pExpr, TERM_VIRTUAL);
+ idxNew = whereClauseInsert(pWC, pExpr, TERM_VIRTUAL|TERM_SLICE);
pWC->a[idxNew].u.x.iField = i+1;
exprAnalyze(pSrc, pWC, idxNew);
markTermAsChild(pWC, idxNew, idxTerm);
}
}
-#ifdef SQLITE_ENABLE_STAT4
- /* When sqlite_stat4 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
- ** virtual term of that form.
- **
- ** Note that the virtual term must be tagged with TERM_VNULL.
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ /* Add a WO_AUX auxiliary term to the constraint set if the
+ ** current expression is of the form "column OP expr" where OP
+ ** is an operator that gets passed into virtual tables but which is
+ ** not normally optimized for ordinary tables. In other words, OP
+ ** is one of MATCH, LIKE, GLOB, REGEXP, !=, IS, IS NOT, or NOT NULL.
+ ** This information is used by the xBestIndex methods of
+ ** virtual tables. The native query optimizer does not attempt
+ ** to do anything with MATCH functions.
*/
- if( pExpr->op==TK_NOTNULL
- && pExpr->pLeft->op==TK_COLUMN
- && pExpr->pLeft->iColumn>=0
- && !ExprHasProperty(pExpr, EP_FromJoin)
- && OptimizationEnabled(db, SQLITE_Stat4)
- ){
- Expr *pNewExpr;
- Expr *pLeft = pExpr->pLeft;
- int idxNew;
- WhereTerm *pNewTerm;
-
- pNewExpr = sqlcipher_sqlite3PExpr(pParse, TK_GT,
- sqlcipher_sqlite3ExprDup(db, pLeft, 0),
- sqlcipher_sqlite3ExprAlloc(db, TK_NULL, 0, 0));
-
- idxNew = whereClauseInsert(pWC, pNewExpr,
- TERM_VIRTUAL|TERM_DYNAMIC|TERM_VNULL);
- if( idxNew ){
- pNewTerm = &pWC->a[idxNew];
- pNewTerm->prereqRight = 0;
- pNewTerm->leftCursor = pLeft->iTable;
- pNewTerm->u.x.leftColumn = pLeft->iColumn;
- pNewTerm->eOperator = WO_GT;
- markTermAsChild(pWC, idxNew, idxTerm);
- pTerm = &pWC->a[idxTerm];
- pTerm->wtFlags |= TERM_COPIED;
- pNewTerm->prereqAll = pTerm->prereqAll;
+ else if( pWC->op==TK_AND ){
+ Expr *pRight = 0, *pLeft = 0;
+ int res = isAuxiliaryVtabOperator(db, pExpr, &eOp2, &pLeft, &pRight);
+ while( res-- > 0 ){
+ int idxNew;
+ WhereTerm *pNewTerm;
+ Bitmask prereqColumn, prereqExpr;
+
+ prereqExpr = sqlcipher_sqlite3WhereExprUsage(pMaskSet, pRight);
+ prereqColumn = sqlcipher_sqlite3WhereExprUsage(pMaskSet, pLeft);
+ if( (prereqExpr & prereqColumn)==0 ){
+ Expr *pNewExpr;
+ pNewExpr = sqlcipher_sqlite3PExpr(pParse, TK_MATCH,
+ 0, sqlcipher_sqlite3ExprDup(db, pRight, 0));
+ if( ExprHasProperty(pExpr, EP_OuterON) && pNewExpr ){
+ ExprSetProperty(pNewExpr, EP_OuterON);
+ pNewExpr->w.iJoin = pExpr->w.iJoin;
+ }
+ idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
+ testcase( idxNew==0 );
+ pNewTerm = &pWC->a[idxNew];
+ pNewTerm->prereqRight = prereqExpr;
+ pNewTerm->leftCursor = pLeft->iTable;
+ pNewTerm->u.x.leftColumn = pLeft->iColumn;
+ pNewTerm->eOperator = WO_AUX;
+ pNewTerm->eMatchOp = eOp2;
+ markTermAsChild(pWC, idxNew, idxTerm);
+ pTerm = &pWC->a[idxTerm];
+ pTerm->wtFlags |= TERM_COPIED;
+ pNewTerm->prereqAll = pTerm->prereqAll;
+ }
+ SWAP(Expr*, pLeft, pRight);
}
}
-#endif /* SQLITE_ENABLE_STAT4 */
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
/* Prevent ON clause terms of a LEFT JOIN from being used to drive
** an index for tables to the left of the join.
@@ -150915,6 +159074,113 @@ SQLITE_PRIVATE void sqlcipher_sqlite3WhereSplit(WhereClause *pWC, Expr *pExpr, u
}
/*
+** Add either a LIMIT (if eMatchOp==SQLITE_INDEX_CONSTRAINT_LIMIT) or
+** OFFSET (if eMatchOp==SQLITE_INDEX_CONSTRAINT_OFFSET) term to the
+** where-clause passed as the first argument. The value for the term
+** is found in register iReg.
+**
+** In the common case where the value is a simple integer
+** (example: "LIMIT 5 OFFSET 10") then the expression codes as a
+** TK_INTEGER so that it will be available to sqlcipher_sqlite3_vtab_rhs_value().
+** If not, then it codes as a TK_REGISTER expression.
+*/
+static void whereAddLimitExpr(
+ WhereClause *pWC, /* Add the constraint to this WHERE clause */
+ int iReg, /* Register that will hold value of the limit/offset */
+ Expr *pExpr, /* Expression that defines the limit/offset */
+ int iCsr, /* Cursor to which the constraint applies */
+ int eMatchOp /* SQLITE_INDEX_CONSTRAINT_LIMIT or _OFFSET */
+){
+ Parse *pParse = pWC->pWInfo->pParse;
+ sqlcipher_sqlite3 *db = pParse->db;
+ Expr *pNew;
+ int iVal = 0;
+
+ if( sqlcipher_sqlite3ExprIsInteger(pExpr, &iVal) && iVal>=0 ){
+ Expr *pVal = sqlcipher_sqlite3Expr(db, TK_INTEGER, 0);
+ if( pVal==0 ) return;
+ ExprSetProperty(pVal, EP_IntValue);
+ pVal->u.iValue = iVal;
+ pNew = sqlcipher_sqlite3PExpr(pParse, TK_MATCH, 0, pVal);
+ }else{
+ Expr *pVal = sqlcipher_sqlite3Expr(db, TK_REGISTER, 0);
+ if( pVal==0 ) return;
+ pVal->iTable = iReg;
+ pNew = sqlcipher_sqlite3PExpr(pParse, TK_MATCH, 0, pVal);
+ }
+ if( pNew ){
+ WhereTerm *pTerm;
+ int idx;
+ idx = whereClauseInsert(pWC, pNew, TERM_DYNAMIC|TERM_VIRTUAL);
+ pTerm = &pWC->a[idx];
+ pTerm->leftCursor = iCsr;
+ pTerm->eOperator = WO_AUX;
+ pTerm->eMatchOp = eMatchOp;
+ }
+}
+
+/*
+** Possibly add terms corresponding to the LIMIT and OFFSET clauses of the
+** SELECT statement passed as the second argument. These terms are only
+** added if:
+**
+** 1. The SELECT statement has a LIMIT clause, and
+** 2. The SELECT statement is not an aggregate or DISTINCT query, and
+** 3. The SELECT statement has exactly one object in its from clause, and
+** that object is a virtual table, and
+** 4. There are no terms in the WHERE clause that will not be passed
+** to the virtual table xBestIndex method.
+** 5. The ORDER BY clause, if any, will be made available to the xBestIndex
+** method.
+**
+** LIMIT and OFFSET terms are ignored by most of the planner code. They
+** exist only so that they may be passed to the xBestIndex method of the
+** single virtual table in the FROM clause of the SELECT.
+*/
+SQLITE_PRIVATE void sqlcipher_sqlite3WhereAddLimit(WhereClause *pWC, Select *p){
+ assert( p==0 || (p->pGroupBy==0 && (p->selFlags & SF_Aggregate)==0) );
+ if( (p && p->pLimit) /* 1 */
+ && (p->selFlags & (SF_Distinct|SF_Aggregate))==0 /* 2 */
+ && (p->pSrc->nSrc==1 && IsVirtual(p->pSrc->a[0].pTab)) /* 3 */
+ ){
+ ExprList *pOrderBy = p->pOrderBy;
+ int iCsr = p->pSrc->a[0].iCursor;
+ int ii;
+
+ /* Check condition (4). Return early if it is not met. */
+ for(ii=0; ii<pWC->nTerm; ii++){
+ if( pWC->a[ii].wtFlags & TERM_CODED ){
+ /* This term is a vector operation that has been decomposed into
+ ** other, subsequent terms. It can be ignored. See tag-20220128a */
+ assert( pWC->a[ii].wtFlags & TERM_VIRTUAL );
+ assert( pWC->a[ii].eOperator==WO_ROWVAL );
+ continue;
+ }
+ if( pWC->a[ii].leftCursor!=iCsr ) return;
+ }
+
+ /* Check condition (5). Return early if it is not met. */
+ if( pOrderBy ){
+ for(ii=0; ii<pOrderBy->nExpr; ii++){
+ Expr *pExpr = pOrderBy->a[ii].pExpr;
+ if( pExpr->op!=TK_COLUMN ) return;
+ if( pExpr->iTable!=iCsr ) return;
+ if( pOrderBy->a[ii].fg.sortFlags & KEYINFO_ORDER_BIGNULL ) return;
+ }
+ }
+
+ /* All conditions are met. Add the terms to the where-clause object. */
+ assert( p->pLimit->op==TK_LIMIT );
+ whereAddLimitExpr(pWC, p->iLimit, p->pLimit->pLeft,
+ iCsr, SQLITE_INDEX_CONSTRAINT_LIMIT);
+ if( p->iOffset>0 ){
+ whereAddLimitExpr(pWC, p->iOffset, p->pLimit->pRight,
+ iCsr, SQLITE_INDEX_CONSTRAINT_OFFSET);
+ }
+ }
+}
+
+/*
** Initialize a preallocated WhereClause structure.
*/
SQLITE_PRIVATE void sqlcipher_sqlite3WhereClauseInit(
@@ -150925,6 +159191,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3WhereClauseInit(
pWC->hasOr = 0;
pWC->pOuter = 0;
pWC->nTerm = 0;
+ pWC->nBase = 0;
pWC->nSlot = ArraySize(pWC->aStatic);
pWC->a = pWC->aStatic;
}
@@ -150935,22 +159202,36 @@ SQLITE_PRIVATE void sqlcipher_sqlite3WhereClauseInit(
** sqlcipher_sqlite3WhereClauseInit().
*/
SQLITE_PRIVATE void sqlcipher_sqlite3WhereClauseClear(WhereClause *pWC){
- int i;
- WhereTerm *a;
sqlcipher_sqlite3 *db = pWC->pWInfo->pParse->db;
- for(i=pWC->nTerm-1, a=pWC->a; i>=0; i--, a++){
- if( a->wtFlags & TERM_DYNAMIC ){
- sqlcipher_sqlite3ExprDelete(db, a->pExpr);
+ assert( pWC->nTerm>=pWC->nBase );
+ if( pWC->nTerm>0 ){
+ WhereTerm *a = pWC->a;
+ WhereTerm *aLast = &pWC->a[pWC->nTerm-1];
+#ifdef SQLITE_DEBUG
+ int i;
+ /* Verify that every term past pWC->nBase is virtual */
+ for(i=pWC->nBase; i<pWC->nTerm; i++){
+ assert( (pWC->a[i].wtFlags & TERM_VIRTUAL)!=0 );
}
- if( a->wtFlags & TERM_ORINFO ){
- whereOrInfoDelete(db, a->u.pOrInfo);
- }else if( a->wtFlags & TERM_ANDINFO ){
- whereAndInfoDelete(db, a->u.pAndInfo);
+#endif
+ while(1){
+ assert( a->eMatchOp==0 || a->eOperator==WO_AUX );
+ if( a->wtFlags & TERM_DYNAMIC ){
+ sqlcipher_sqlite3ExprDelete(db, a->pExpr);
+ }
+ if( a->wtFlags & (TERM_ORINFO|TERM_ANDINFO) ){
+ if( a->wtFlags & TERM_ORINFO ){
+ assert( (a->wtFlags & TERM_ANDINFO)==0 );
+ whereOrInfoDelete(db, a->u.pOrInfo);
+ }else{
+ assert( (a->wtFlags & TERM_ANDINFO)!=0 );
+ whereAndInfoDelete(db, a->u.pAndInfo);
+ }
+ }
+ if( a==aLast ) break;
+ a++;
}
}
- if( pWC->a!=pWC->aStatic ){
- sqlcipher_sqlite3DbFree(db, pWC->a);
- }
}
@@ -150958,28 +159239,52 @@ SQLITE_PRIVATE void sqlcipher_sqlite3WhereClauseClear(WhereClause *pWC){
** These routines walk (recursively) an expression tree and generate
** a bitmask indicating which tables are used in that expression
** tree.
+**
+** sqlcipher_sqlite3WhereExprUsage(MaskSet, Expr) ->
+**
+** Return a Bitmask of all tables referenced by Expr. Expr can be
+** be NULL, in which case 0 is returned.
+**
+** sqlcipher_sqlite3WhereExprUsageNN(MaskSet, Expr) ->
+**
+** Same as sqlcipher_sqlite3WhereExprUsage() except that Expr must not be
+** NULL. The "NN" suffix on the name stands for "Not Null".
+**
+** sqlcipher_sqlite3WhereExprListUsage(MaskSet, ExprList) ->
+**
+** Return a Bitmask of all tables referenced by every expression
+** in the expression list ExprList. ExprList can be NULL, in which
+** case 0 is returned.
+**
+** sqlcipher_sqlite3WhereExprUsageFull(MaskSet, ExprList) ->
+**
+** Internal use only. Called only by sqlcipher_sqlite3WhereExprUsageNN() for
+** complex expressions that require pushing register values onto
+** the stack. Many calls to sqlcipher_sqlite3WhereExprUsageNN() do not need
+** the more complex analysis done by this routine. Hence, the
+** computations done by this routine are broken out into a separate
+** "no-inline" function to avoid the stack push overhead in the
+** common case where it is not needed.
*/
-SQLITE_PRIVATE Bitmask sqlcipher_sqlite3WhereExprUsageNN(WhereMaskSet *pMaskSet, Expr *p){
+static SQLITE_NOINLINE Bitmask sqlcipher_sqlite3WhereExprUsageFull(
+ WhereMaskSet *pMaskSet,
+ Expr *p
+){
Bitmask mask;
- if( p->op==TK_COLUMN && !ExprHasProperty(p, EP_FixedCol) ){
- return sqlcipher_sqlite3WhereGetMask(pMaskSet, p->iTable);
- }else if( ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){
- assert( p->op!=TK_IF_NULL_ROW );
- return 0;
- }
mask = (p->op==TK_IF_NULL_ROW) ? sqlcipher_sqlite3WhereGetMask(pMaskSet, p->iTable) : 0;
if( p->pLeft ) mask |= sqlcipher_sqlite3WhereExprUsageNN(pMaskSet, p->pLeft);
if( p->pRight ){
mask |= sqlcipher_sqlite3WhereExprUsageNN(pMaskSet, p->pRight);
assert( p->x.pList==0 );
- }else if( ExprHasProperty(p, EP_xIsSelect) ){
+ }else if( ExprUseXSelect(p) ){
if( ExprHasProperty(p, EP_VarSelect) ) pMaskSet->bVarSelect = 1;
mask |= exprSelectUsage(pMaskSet, p->x.pSelect);
}else if( p->x.pList ){
mask |= sqlcipher_sqlite3WhereExprListUsage(pMaskSet, p->x.pList);
}
#ifndef SQLITE_OMIT_WINDOWFUNC
- if( (p->op==TK_FUNCTION || p->op==TK_AGG_FUNCTION) && p->y.pWin ){
+ if( (p->op==TK_FUNCTION || p->op==TK_AGG_FUNCTION) && ExprUseYWin(p) ){
+ assert( p->y.pWin!=0 );
mask |= sqlcipher_sqlite3WhereExprListUsage(pMaskSet, p->y.pWin->pPartition);
mask |= sqlcipher_sqlite3WhereExprListUsage(pMaskSet, p->y.pWin->pOrderBy);
mask |= sqlcipher_sqlite3WhereExprUsage(pMaskSet, p->y.pWin->pFilter);
@@ -150987,6 +159292,15 @@ SQLITE_PRIVATE Bitmask sqlcipher_sqlite3WhereExprUsageNN(WhereMaskSet *pMaskSet,
#endif
return mask;
}
+SQLITE_PRIVATE Bitmask sqlcipher_sqlite3WhereExprUsageNN(WhereMaskSet *pMaskSet, Expr *p){
+ if( p->op==TK_COLUMN && !ExprHasProperty(p, EP_FixedCol) ){
+ return sqlcipher_sqlite3WhereGetMask(pMaskSet, p->iTable);
+ }else if( ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){
+ assert( p->op!=TK_IF_NULL_ROW );
+ return 0;
+ }
+ return sqlcipher_sqlite3WhereExprUsageFull(pMaskSet, p);
+}
SQLITE_PRIVATE Bitmask sqlcipher_sqlite3WhereExprUsage(WhereMaskSet *pMaskSet, Expr *p){
return p ? sqlcipher_sqlite3WhereExprUsageNN(pMaskSet,p) : 0;
}
@@ -151029,7 +159343,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3WhereExprAnalyze(
*/
SQLITE_PRIVATE void sqlcipher_sqlite3WhereTabFuncArgs(
Parse *pParse, /* Parsing context */
- struct SrcList_item *pItem, /* The FROM clause term to process */
+ SrcItem *pItem, /* The FROM clause term to process */
WhereClause *pWC /* Xfer function arguments to here */
){
Table *pTab;
@@ -151044,6 +159358,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3WhereTabFuncArgs(
if( pArgs==0 ) return;
for(j=k=0; j<pArgs->nExpr; j++){
Expr *pRhs;
+ u32 joinType;
while( k<pTab->nCol && (pTab->aCol[k].colFlags & COLFLAG_HIDDEN)==0 ){k++;}
if( k>=pTab->nCol ){
sqlcipher_sqlite3ErrorMsg(pParse, "too many arguments on %s() - max %d",
@@ -151054,13 +159369,18 @@ SQLITE_PRIVATE void sqlcipher_sqlite3WhereTabFuncArgs(
if( pColRef==0 ) return;
pColRef->iTable = pItem->iCursor;
pColRef->iColumn = k++;
+ assert( ExprUseYTab(pColRef) );
pColRef->y.pTab = pTab;
+ pItem->colUsed |= sqlcipher_sqlite3ExprColUsed(pColRef);
pRhs = sqlcipher_sqlite3PExpr(pParse, TK_UPLUS,
sqlcipher_sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0), 0);
pTerm = sqlcipher_sqlite3PExpr(pParse, TK_EQ, pColRef, pRhs);
- if( pItem->fg.jointype & JT_LEFT ){
- sqlcipher_sqlite3SetJoinExpr(pTerm, pItem->iCursor);
+ if( pItem->fg.jointype & (JT_LEFT|JT_LTORJ) ){
+ joinType = EP_OuterON;
+ }else{
+ joinType = EP_InnerON;
}
+ sqlcipher_sqlite3SetJoinExpr(pTerm, pItem->iCursor, joinType);
whereClauseInsert(pWC, pTerm, TERM_DYNAMIC);
}
}
@@ -151099,19 +159419,19 @@ SQLITE_PRIVATE void sqlcipher_sqlite3WhereTabFuncArgs(
*/
typedef struct HiddenIndexInfo HiddenIndexInfo;
struct HiddenIndexInfo {
- WhereClause *pWC; /* The Where clause being analyzed */
- Parse *pParse; /* The parsing context */
+ WhereClause *pWC; /* The Where clause being analyzed */
+ Parse *pParse; /* The parsing context */
+ int eDistinct; /* Value to return from sqlcipher_sqlite3_vtab_distinct() */
+ u32 mIn; /* Mask of terms that are <col> IN (...) */
+ u32 mHandleIn; /* Terms that vtab will handle as <col> IN (...) */
+ sqlcipher_sqlite3_value *aRhs[1]; /* RHS values for constraints. MUST BE LAST
+ ** because extra space is allocated to hold up
+ ** to nTerm such values */
};
/* Forward declaration of methods */
static int whereLoopResize(sqlcipher_sqlite3*, WhereLoop*, int);
-/* Test variable that can be set to enable WHERE tracing */
-#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
-/***/ int sqlcipher_sqlite3WhereTrace = 0;
-#endif
-
-
/*
** Return the estimated number of output rows from a WHERE clause
*/
@@ -151171,7 +159491,33 @@ SQLITE_PRIVATE int sqlcipher_sqlite3WhereOrderByLimitOptLabel(WhereInfo *pWInfo)
}
pInner = &pWInfo->a[pWInfo->nLevel-1];
assert( pInner->addrNxt!=0 );
- return pInner->addrNxt;
+ return pInner->pRJ ? pWInfo->iContinue : pInner->addrNxt;
+}
+
+/*
+** While generating code for the min/max optimization, after handling
+** the aggregate-step call to min() or max(), check to see if any
+** additional looping is required. If the output order is such that
+** we are certain that the correct answer has already been found, then
+** code an OP_Goto to by pass subsequent processing.
+**
+** Any extra OP_Goto that is coded here is an optimization. The
+** correct answer should be obtained regardless. This OP_Goto just
+** makes the answer appear faster.
+*/
+SQLITE_PRIVATE void sqlcipher_sqlite3WhereMinMaxOptEarlyOut(Vdbe *v, WhereInfo *pWInfo){
+ WhereLevel *pInner;
+ int i;
+ if( !pWInfo->bOrderedInnerLoop ) return;
+ if( pWInfo->nOBSat==0 ) return;
+ for(i=pWInfo->nLevel-1; i>=0; i--){
+ pInner = &pWInfo->a[i];
+ if( (pInner->pWLoop->wsFlags & WHERE_COLUMN_IN)!=0 ){
+ sqlcipher_sqlite3VdbeGoto(v, pInner->addrNxt);
+ return;
+ }
+ }
+ sqlcipher_sqlite3VdbeGoto(v, pWInfo->iBreak);
}
/*
@@ -151283,7 +159629,12 @@ whereOrInsert_done:
SQLITE_PRIVATE Bitmask sqlcipher_sqlite3WhereGetMask(WhereMaskSet *pMaskSet, int iCursor){
int i;
assert( pMaskSet->n<=(int)sizeof(Bitmask)*8 );
- for(i=0; i<pMaskSet->n; i++){
+ assert( pMaskSet->n>0 || pMaskSet->ix[0]<0 );
+ assert( iCursor>=-1 );
+ if( pMaskSet->ix[0]==iCursor ){
+ return 1;
+ }
+ for(i=1; i<pMaskSet->n; i++){
if( pMaskSet->ix[i]==iCursor ){
return MASKBIT(i);
}
@@ -151291,6 +159642,30 @@ SQLITE_PRIVATE Bitmask sqlcipher_sqlite3WhereGetMask(WhereMaskSet *pMaskSet, int
return 0;
}
+/* Allocate memory that is automatically freed when pWInfo is freed.
+*/
+SQLITE_PRIVATE void *sqlcipher_sqlite3WhereMalloc(WhereInfo *pWInfo, u64 nByte){
+ WhereMemBlock *pBlock;
+ pBlock = sqlcipher_sqlite3DbMallocRawNN(pWInfo->pParse->db, nByte+sizeof(*pBlock));
+ if( pBlock ){
+ pBlock->pNext = pWInfo->pMemToFree;
+ pBlock->sz = nByte;
+ pWInfo->pMemToFree = pBlock;
+ pBlock++;
+ }
+ return (void*)pBlock;
+}
+SQLITE_PRIVATE void *sqlcipher_sqlite3WhereRealloc(WhereInfo *pWInfo, void *pOld, u64 nByte){
+ void *pNew = sqlcipher_sqlite3WhereMalloc(pWInfo, nByte);
+ if( pNew && pOld ){
+ WhereMemBlock *pOldBlk = (WhereMemBlock*)pOld;
+ pOldBlk--;
+ assert( pOldBlk->sz<nByte );
+ memcpy(pNew, pOld, pOldBlk->sz);
+ }
+ return pNew;
+}
+
/*
** Create a new mask for cursor iCursor.
**
@@ -151310,7 +159685,9 @@ static void createMask(WhereMaskSet *pMaskSet, int iCursor){
*/
static Expr *whereRightSubexprIsColumn(Expr *p){
p = sqlcipher_sqlite3ExprSkipCollateAndLikely(p->pRight);
- if( ALWAYS(p!=0) && p->op==TK_COLUMN ) return p;
+ if( ALWAYS(p!=0) && p->op==TK_COLUMN && !ExprHasProperty(p, EP_FixedCol) ){
+ return p;
+ }
return 0;
}
@@ -151333,14 +159710,16 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
iColumn = pScan->aiColumn[pScan->iEquiv-1];
iCur = pScan->aiCur[pScan->iEquiv-1];
assert( pWC!=0 );
+ assert( iCur>=0 );
do{
for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){
+ assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 || pTerm->leftCursor<0 );
if( pTerm->leftCursor==iCur
&& pTerm->u.x.leftColumn==iColumn
&& (iColumn!=XN_EXPR
|| sqlcipher_sqlite3ExprCompareSkip(pTerm->pExpr->pLeft,
pScan->pIdxExpr,iCur)==0)
- && (pScan->iEquiv<=1 || !ExprHasProperty(pTerm->pExpr, EP_FromJoin))
+ && (pScan->iEquiv<=1 || !ExprHasProperty(pTerm->pExpr, EP_OuterON))
){
if( (pTerm->eOperator & WO_EQUIV)!=0
&& pScan->nEquiv<ArraySize(pScan->aiCur)
@@ -151376,7 +159755,8 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
}
}
if( (pTerm->eOperator & (WO_EQ|WO_IS))!=0
- && (pX = pTerm->pExpr->pRight)->op==TK_COLUMN
+ && (pX = pTerm->pExpr->pRight, ALWAYS(pX!=0))
+ && pX->op==TK_COLUMN
&& pX->iTable==pScan->aiCur[0]
&& pX->iColumn==pScan->aiColumn[0]
){
@@ -151385,6 +159765,18 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
}
pScan->pWC = pWC;
pScan->k = k+1;
+#ifdef WHERETRACE_ENABLED
+ if( sqlcipher_sqlite3WhereTrace & 0x20000 ){
+ int ii;
+ sqlcipher_sqlite3DebugPrintf("SCAN-TERM %p: nEquiv=%d",
+ pTerm, pScan->nEquiv);
+ for(ii=0; ii<pScan->nEquiv; ii++){
+ sqlcipher_sqlite3DebugPrintf(" {%d:%d}",
+ pScan->aiCur[ii], pScan->aiColumn[ii]);
+ }
+ sqlcipher_sqlite3DebugPrintf("\n");
+ }
+#endif
return pTerm;
}
}
@@ -151451,16 +159843,16 @@ static WhereTerm *whereScanInit(
if( pIdx ){
int j = iColumn;
iColumn = pIdx->aiColumn[j];
- if( iColumn==XN_EXPR ){
- pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr;
- pScan->zCollName = pIdx->azColl[j];
- pScan->aiColumn[0] = XN_EXPR;
- return whereScanInitIndexExpr(pScan);
- }else if( iColumn==pIdx->pTable->iPKey ){
+ if( iColumn==pIdx->pTable->iPKey ){
iColumn = XN_ROWID;
}else if( iColumn>=0 ){
pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity;
pScan->zCollName = pIdx->azColl[j];
+ }else if( iColumn==XN_EXPR ){
+ pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr;
+ pScan->zCollName = pIdx->azColl[j];
+ pScan->aiColumn[0] = XN_EXPR;
+ return whereScanInitIndexExpr(pScan);
}
}else if( iColumn==XN_EXPR ){
return 0;
@@ -151541,7 +159933,7 @@ static int findIndexCol(
for(i=0; i<pList->nExpr; i++){
Expr *p = sqlcipher_sqlite3ExprSkipCollateAndLikely(pList->a[i].pExpr);
if( ALWAYS(p!=0)
- && p->op==TK_COLUMN
+ && (p->op==TK_COLUMN || p->op==TK_AGG_COLUMN)
&& p->iColumn==pIdx->aiColumn[iCol]
&& p->iTable==iBase
){
@@ -151606,7 +159998,8 @@ static int isDistinctRedundant(
for(i=0; i<pDistinct->nExpr; i++){
Expr *p = sqlcipher_sqlite3ExprSkipCollateAndLikely(pDistinct->a[i].pExpr);
if( NEVER(p==0) ) continue;
- if( p->op==TK_COLUMN && p->iTable==iBase && p->iColumn<0 ) return 1;
+ if( p->op!=TK_COLUMN && p->op!=TK_AGG_COLUMN ) continue;
+ if( p->iTable==iBase && p->iColumn<0 ) return 1;
}
/* Loop through all indices on the table, checking each to see if it makes
@@ -151624,6 +160017,7 @@ static int isDistinctRedundant(
*/
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
if( !IsUniqueIndex(pIdx) ) continue;
+ if( pIdx->pPartIdxWhere ) continue;
for(i=0; i<pIdx->nKeyCol; i++){
if( 0==sqlcipher_sqlite3WhereFindTerm(pWC, iBase, i, ~(Bitmask)0, WO_EQ, pIdx) ){
if( findIndexCol(pParse, pDistinct, iBase, pIdx, i)<0 ) break;
@@ -151677,15 +160071,16 @@ static void translateColumnToCopy(
pOp->p1 = pOp->p2 + iRegister;
pOp->p2 = pOp->p3;
pOp->p3 = 0;
+ pOp->p5 = 2; /* Cause the MEM_Subtype flag to be cleared */
}else if( pOp->opcode==OP_Rowid ){
- if( iAutoidxCur ){
- pOp->opcode = OP_Sequence;
- pOp->p1 = iAutoidxCur;
- }else{
+ pOp->opcode = OP_Sequence;
+ pOp->p1 = iAutoidxCur;
+#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
+ if( iAutoidxCur==0 ){
pOp->opcode = OP_Null;
- pOp->p1 = 0;
pOp->p3 = 0;
}
+#endif
}
}
}
@@ -151701,12 +160096,14 @@ static void whereTraceIndexInfoInputs(sqlcipher_sqlite3_index_info *p){
int i;
if( !sqlcipher_sqlite3WhereTrace ) return;
for(i=0; i<p->nConstraint; i++){
- sqlcipher_sqlite3DebugPrintf(" constraint[%d]: col=%d termid=%d op=%d usabled=%d\n",
+ sqlcipher_sqlite3DebugPrintf(
+ " constraint[%d]: col=%d termid=%d op=%d usabled=%d collseq=%s\n",
i,
p->aConstraint[i].iColumn,
p->aConstraint[i].iTermOffset,
p->aConstraint[i].op,
- p->aConstraint[i].usable);
+ p->aConstraint[i].usable,
+ sqlcipher_sqlite3_vtab_collation(p,i));
}
for(i=0; i<p->nOrderBy; i++){
sqlcipher_sqlite3DebugPrintf(" orderby[%d]: col=%d desc=%d\n",
@@ -151742,23 +160139,27 @@ static void whereTraceIndexInfoOutputs(sqlcipher_sqlite3_index_info *p){
** index existed.
*/
static int termCanDriveIndex(
- WhereTerm *pTerm, /* WHERE clause term to check */
- struct SrcList_item *pSrc, /* Table we are trying to access */
- Bitmask notReady /* Tables in outer loops of the join */
+ const WhereTerm *pTerm, /* WHERE clause term to check */
+ const SrcItem *pSrc, /* Table we are trying to access */
+ const Bitmask notReady /* Tables in outer loops of the join */
){
char aff;
if( pTerm->leftCursor!=pSrc->iCursor ) return 0;
if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) return 0;
- if( (pSrc->fg.jointype & JT_LEFT)
- && !ExprHasProperty(pTerm->pExpr, EP_FromJoin)
- && (pTerm->eOperator & WO_IS)
- ){
- /* Cannot use an IS term from the WHERE clause as an index driver for
- ** the RHS of a LEFT JOIN. Such a term can only be used if it is from
- ** the ON clause. */
- return 0;
+ assert( (pSrc->fg.jointype & JT_RIGHT)==0 );
+ if( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0 ){
+ testcase( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))==JT_LEFT );
+ testcase( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))==JT_LTORJ );
+ testcase( ExprHasProperty(pTerm->pExpr, EP_OuterON) )
+ testcase( ExprHasProperty(pTerm->pExpr, EP_InnerON) );
+ if( !ExprHasProperty(pTerm->pExpr, EP_OuterON|EP_InnerON)
+ || pTerm->pExpr->w.iJoin != pSrc->iCursor
+ ){
+ return 0; /* See tag-20191211-001 */
+ }
}
if( (pTerm->prereqRight & notReady)!=0 ) return 0;
+ assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
if( pTerm->u.x.leftColumn<0 ) return 0;
aff = pSrc->pTab->aCol[pTerm->u.x.leftColumn].affinity;
if( !sqlcipher_sqlite3IndexAffinityOk(pTerm->pExpr, aff) ) return 0;
@@ -151774,11 +160175,11 @@ static int termCanDriveIndex(
** and to set up the WhereLevel object pLevel so that the code generator
** makes use of the automatic index.
*/
-static void constructAutomaticIndex(
+static SQLITE_NOINLINE void constructAutomaticIndex(
Parse *pParse, /* The parsing context */
- WhereClause *pWC, /* The WHERE clause */
- struct SrcList_item *pSrc, /* The FROM clause term to get the next index */
- Bitmask notReady, /* Mask of cursors that are not available */
+ const WhereClause *pWC, /* The WHERE clause */
+ const SrcItem *pSrc, /* The FROM clause term to get the next index */
+ const Bitmask notReady, /* Mask of cursors that are not available */
WhereLevel *pLevel /* Write new index here */
){
int nKeyCol; /* Number of columns in the constructed index */
@@ -151801,7 +160202,7 @@ static void constructAutomaticIndex(
u8 sentWarning = 0; /* True if a warnning has been issued */
Expr *pPartial = 0; /* Partial Index Expression */
int iContinue = 0; /* Jump here to skip excluded rows */
- struct SrcList_item *pTabItem; /* FROM clause term being indexed */
+ SrcItem *pTabItem; /* FROM clause term being indexed */
int addrCounter = 0; /* Address where integer counter is initialized */
int regBase; /* Array of registers where record is assembled */
@@ -151820,25 +160221,27 @@ static void constructAutomaticIndex(
idxCols = 0;
for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
Expr *pExpr = pTerm->pExpr;
- assert( !ExprHasProperty(pExpr, EP_FromJoin) /* prereq always non-zero */
- || pExpr->iRightJoinTable!=pSrc->iCursor /* for the right-hand */
- || pLoop->prereq!=0 ); /* table of a LEFT JOIN */
- if( pLoop->prereq==0
- && (pTerm->wtFlags & TERM_VIRTUAL)==0
- && !ExprHasProperty(pExpr, EP_FromJoin)
- && sqlcipher_sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor) ){
+ /* Make the automatic index a partial index if there are terms in the
+ ** WHERE clause (or the ON clause of a LEFT join) that constrain which
+ ** rows of the target table (pSrc) that can be used. */
+ if( (pTerm->wtFlags & TERM_VIRTUAL)==0
+ && sqlcipher_sqlite3ExprIsTableConstraint(pExpr, pSrc)
+ ){
pPartial = sqlcipher_sqlite3ExprAnd(pParse, pPartial,
sqlcipher_sqlite3ExprDup(pParse->db, pExpr, 0));
}
if( termCanDriveIndex(pTerm, pSrc, notReady) ){
- int iCol = pTerm->u.x.leftColumn;
- Bitmask cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol);
+ int iCol;
+ Bitmask cMask;
+ assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
+ iCol = pTerm->u.x.leftColumn;
+ cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol);
testcase( iCol==BMS );
testcase( iCol==BMS-1 );
if( !sentWarning ){
sqlcipher_sqlite3_log(SQLITE_WARNING_AUTOINDEX,
"automatic index on %s(%s)", pTable->zName,
- pTable->aCol[iCol].zName);
+ pTable->aCol[iCol].zCnName);
sentWarning = 1;
}
if( (idxCols & cMask)==0 ){
@@ -151850,7 +160253,7 @@ static void constructAutomaticIndex(
}
}
}
- assert( nKeyCol>0 );
+ assert( nKeyCol>0 || pParse->db->mallocFailed );
pLoop->u.btree.nEq = pLoop->nLTerm = nKeyCol;
pLoop->wsFlags = WHERE_COLUMN_EQ | WHERE_IDX_ONLY | WHERE_INDEXED
| WHERE_AUTO_INDEX;
@@ -151884,8 +160287,11 @@ static void constructAutomaticIndex(
idxCols = 0;
for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
if( termCanDriveIndex(pTerm, pSrc, notReady) ){
- int iCol = pTerm->u.x.leftColumn;
- Bitmask cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol);
+ int iCol;
+ Bitmask cMask;
+ assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
+ iCol = pTerm->u.x.leftColumn;
+ cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol);
testcase( iCol==BMS-1 );
testcase( iCol==BMS );
if( (idxCols & cMask)==0 ){
@@ -151927,6 +160333,10 @@ static void constructAutomaticIndex(
sqlcipher_sqlite3VdbeAddOp2(v, OP_OpenAutoindex, pLevel->iIdxCur, nKeyCol+1);
sqlcipher_sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
VdbeComment((v, "for %s", pTable->zName));
+ if( OptimizationEnabled(pParse->db, SQLITE_BloomFilter) ){
+ pLevel->regFilter = ++pParse->nMem;
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_Blob, 10000, pLevel->regFilter);
+ }
/* Fill the automatic index with content */
pTabItem = &pWC->pWInfo->pTabList->a[pLevel->iFrom];
@@ -151949,6 +160359,10 @@ static void constructAutomaticIndex(
regBase = sqlcipher_sqlite3GenerateIndexKey(
pParse, pIdx, pLevel->iTabCur, regRecord, 0, 0, 0, 0
);
+ if( pLevel->regFilter ){
+ sqlcipher_sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pLevel->regFilter, 0,
+ regBase, pLoop->u.btree.nEq);
+ }
sqlcipher_sqlite3VdbeAddOp2(v, OP_IdxInsert, pLevel->iIdxCur, regRecord);
sqlcipher_sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
if( pPartial ) sqlcipher_sqlite3VdbeResolveLabel(v, iContinue);
@@ -151975,22 +160389,149 @@ end_auto_index_create:
}
#endif /* SQLITE_OMIT_AUTOMATIC_INDEX */
+/*
+** Generate bytecode that will initialize a Bloom filter that is appropriate
+** for pLevel.
+**
+** If there are inner loops within pLevel that have the WHERE_BLOOMFILTER
+** flag set, initialize a Bloomfilter for them as well. Except don't do
+** this recursive initialization if the SQLITE_BloomPulldown optimization has
+** been turned off.
+**
+** When the Bloom filter is initialized, the WHERE_BLOOMFILTER flag is cleared
+** from the loop, but the regFilter value is set to a register that implements
+** the Bloom filter. When regFilter is positive, the
+** sqlcipher_sqlite3WhereCodeOneLoopStart() will generate code to test the Bloom filter
+** and skip the subsequence B-Tree seek if the Bloom filter indicates that
+** no matching rows exist.
+**
+** This routine may only be called if it has previously been determined that
+** the loop would benefit from a Bloom filter, and the WHERE_BLOOMFILTER bit
+** is set.
+*/
+static SQLITE_NOINLINE void sqlcipher_sqlite3ConstructBloomFilter(
+ WhereInfo *pWInfo, /* The WHERE clause */
+ int iLevel, /* Index in pWInfo->a[] that is pLevel */
+ WhereLevel *pLevel, /* Make a Bloom filter for this FROM term */
+ Bitmask notReady /* Loops that are not ready */
+){
+ int addrOnce; /* Address of opening OP_Once */
+ int addrTop; /* Address of OP_Rewind */
+ int addrCont; /* Jump here to skip a row */
+ const WhereTerm *pTerm; /* For looping over WHERE clause terms */
+ const WhereTerm *pWCEnd; /* Last WHERE clause term */
+ Parse *pParse = pWInfo->pParse; /* Parsing context */
+ Vdbe *v = pParse->pVdbe; /* VDBE under construction */
+ WhereLoop *pLoop = pLevel->pWLoop; /* The loop being coded */
+ int iCur; /* Cursor for table getting the filter */
+
+ assert( pLoop!=0 );
+ assert( v!=0 );
+ assert( pLoop->wsFlags & WHERE_BLOOMFILTER );
+
+ addrOnce = sqlcipher_sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
+ do{
+ const SrcItem *pItem;
+ const Table *pTab;
+ u64 sz;
+ sqlcipher_sqlite3WhereExplainBloomFilter(pParse, pWInfo, pLevel);
+ addrCont = sqlcipher_sqlite3VdbeMakeLabel(pParse);
+ iCur = pLevel->iTabCur;
+ pLevel->regFilter = ++pParse->nMem;
+
+ /* The Bloom filter is a Blob held in a register. Initialize it
+ ** to zero-filled blob of at least 80K bits, but maybe more if the
+ ** estimated size of the table is larger. We could actually
+ ** measure the size of the table at run-time using OP_Count with
+ ** P3==1 and use that value to initialize the blob. But that makes
+ ** testing complicated. By basing the blob size on the value in the
+ ** sqlite_stat1 table, testing is much easier.
+ */
+ pItem = &pWInfo->pTabList->a[pLevel->iFrom];
+ assert( pItem!=0 );
+ pTab = pItem->pTab;
+ assert( pTab!=0 );
+ sz = sqlcipher_sqlite3LogEstToInt(pTab->nRowLogEst);
+ if( sz<10000 ){
+ sz = 10000;
+ }else if( sz>10000000 ){
+ sz = 10000000;
+ }
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_Blob, (int)sz, pLevel->regFilter);
+
+ addrTop = sqlcipher_sqlite3VdbeAddOp1(v, OP_Rewind, iCur); VdbeCoverage(v);
+ pWCEnd = &pWInfo->sWC.a[pWInfo->sWC.nTerm];
+ for(pTerm=pWInfo->sWC.a; pTerm<pWCEnd; pTerm++){
+ Expr *pExpr = pTerm->pExpr;
+ if( (pTerm->wtFlags & TERM_VIRTUAL)==0
+ && sqlcipher_sqlite3ExprIsTableConstraint(pExpr, pItem)
+ ){
+ sqlcipher_sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL);
+ }
+ }
+ if( pLoop->wsFlags & WHERE_IPK ){
+ int r1 = sqlcipher_sqlite3GetTempReg(pParse);
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_Rowid, iCur, r1);
+ sqlcipher_sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pLevel->regFilter, 0, r1, 1);
+ sqlcipher_sqlite3ReleaseTempReg(pParse, r1);
+ }else{
+ Index *pIdx = pLoop->u.btree.pIndex;
+ int n = pLoop->u.btree.nEq;
+ int r1 = sqlcipher_sqlite3GetTempRange(pParse, n);
+ int jj;
+ for(jj=0; jj<n; jj++){
+ int iCol = pIdx->aiColumn[jj];
+ assert( pIdx->pTable==pItem->pTab );
+ sqlcipher_sqlite3ExprCodeGetColumnOfTable(v, pIdx->pTable, iCur, iCol,r1+jj);
+ }
+ sqlcipher_sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pLevel->regFilter, 0, r1, n);
+ sqlcipher_sqlite3ReleaseTempRange(pParse, r1, n);
+ }
+ sqlcipher_sqlite3VdbeResolveLabel(v, addrCont);
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1);
+ VdbeCoverage(v);
+ sqlcipher_sqlite3VdbeJumpHere(v, addrTop);
+ pLoop->wsFlags &= ~WHERE_BLOOMFILTER;
+ if( OptimizationDisabled(pParse->db, SQLITE_BloomPulldown) ) break;
+ while( ++iLevel < pWInfo->nLevel ){
+ const SrcItem *pTabItem;
+ pLevel = &pWInfo->a[iLevel];
+ pTabItem = &pWInfo->pTabList->a[pLevel->iFrom];
+ if( pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ) ) continue;
+ pLoop = pLevel->pWLoop;
+ if( NEVER(pLoop==0) ) continue;
+ if( pLoop->prereq & notReady ) continue;
+ if( (pLoop->wsFlags & (WHERE_BLOOMFILTER|WHERE_COLUMN_IN))
+ ==WHERE_BLOOMFILTER
+ ){
+ /* This is a candidate for bloom-filter pull-down (early evaluation).
+ ** The test that WHERE_COLUMN_IN is omitted is important, as we are
+ ** not able to do early evaluation of bloom filters that make use of
+ ** the IN operator */
+ break;
+ }
+ }
+ }while( iLevel < pWInfo->nLevel );
+ sqlcipher_sqlite3VdbeJumpHere(v, addrOnce);
+}
+
+
#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
** Allocate and populate an sqlcipher_sqlite3_index_info structure. It is the
** responsibility of the caller to eventually release the structure
-** by passing the pointer returned by this function to sqlcipher_sqlite3_free().
+** by passing the pointer returned by this function to freeIndexInfo().
*/
static sqlcipher_sqlite3_index_info *allocateIndexInfo(
- Parse *pParse, /* The parsing context */
+ WhereInfo *pWInfo, /* The WHERE clause */
WhereClause *pWC, /* The WHERE clause being analyzed */
Bitmask mUnusable, /* Ignore terms with these prereqs */
- struct SrcList_item *pSrc, /* The FROM clause term that is the vtab */
- ExprList *pOrderBy, /* The ORDER BY clause */
+ SrcItem *pSrc, /* The FROM clause term that is the vtab */
u16 *pmNoOmit /* Mask of terms not to omit */
){
int i, j;
int nTerm;
+ Parse *pParse = pWInfo->pParse;
struct sqlcipher_sqlite3_index_constraint *pIdxCons;
struct sqlcipher_sqlite3_index_orderby *pIdxOrderBy;
struct sqlcipher_sqlite3_index_constraint_usage *pUsage;
@@ -151999,10 +160540,21 @@ static sqlcipher_sqlite3_index_info *allocateIndexInfo(
int nOrderBy;
sqlcipher_sqlite3_index_info *pIdxInfo;
u16 mNoOmit = 0;
+ const Table *pTab;
+ int eDistinct = 0;
+ ExprList *pOrderBy = pWInfo->pOrderBy;
- /* Count the number of possible WHERE clause constraints referring
- ** to this virtual table */
+ assert( pSrc!=0 );
+ pTab = pSrc->pTab;
+ assert( pTab!=0 );
+ assert( IsVirtual(pTab) );
+
+ /* Find all WHERE clause constraints referring to this virtual table.
+ ** Mark each term with the TERM_OK flag. Set nTerm to the number of
+ ** terms found.
+ */
for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
+ pTerm->wtFlags &= ~TERM_OK;
if( pTerm->leftCursor != pSrc->iCursor ) continue;
if( pTerm->prereqRight & mUnusable ) continue;
assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) );
@@ -152012,8 +160564,29 @@ static sqlcipher_sqlite3_index_info *allocateIndexInfo(
testcase( pTerm->eOperator & WO_ALL );
if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue;
if( pTerm->wtFlags & TERM_VNULL ) continue;
- assert( pTerm->u.x.leftColumn>=(-1) );
+
+ assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
+ assert( pTerm->u.x.leftColumn>=XN_ROWID );
+ assert( pTerm->u.x.leftColumn<pTab->nCol );
+
+ /* tag-20191211-002: WHERE-clause constraints are not useful to the
+ ** right-hand table of a LEFT JOIN nor to the either table of a
+ ** RIGHT JOIN. See tag-20191211-001 for the
+ ** equivalent restriction for ordinary tables. */
+ if( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0 ){
+ testcase( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))==JT_LEFT );
+ testcase( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))==JT_RIGHT );
+ testcase( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))==JT_LTORJ );
+ testcase( ExprHasProperty(pTerm->pExpr, EP_OuterON) );
+ testcase( ExprHasProperty(pTerm->pExpr, EP_InnerON) );
+ if( !ExprHasProperty(pTerm->pExpr, EP_OuterON|EP_InnerON)
+ || pTerm->pExpr->w.iJoin != pSrc->iCursor
+ ){
+ continue;
+ }
+ }
nTerm++;
+ pTerm->wtFlags |= TERM_OK;
}
/* If the ORDER BY clause contains only columns in the current
@@ -152025,11 +160598,49 @@ static sqlcipher_sqlite3_index_info *allocateIndexInfo(
int n = pOrderBy->nExpr;
for(i=0; i<n; i++){
Expr *pExpr = pOrderBy->a[i].pExpr;
- if( pExpr->op!=TK_COLUMN || pExpr->iTable!=pSrc->iCursor ) break;
- if( pOrderBy->a[i].sortFlags & KEYINFO_ORDER_BIGNULL ) break;
+ Expr *pE2;
+
+ /* Skip over constant terms in the ORDER BY clause */
+ if( sqlcipher_sqlite3ExprIsConstant(pExpr) ){
+ continue;
+ }
+
+ /* Virtual tables are unable to deal with NULLS FIRST */
+ if( pOrderBy->a[i].fg.sortFlags & KEYINFO_ORDER_BIGNULL ) break;
+
+ /* First case - a direct column references without a COLLATE operator */
+ if( pExpr->op==TK_COLUMN && pExpr->iTable==pSrc->iCursor ){
+ assert( pExpr->iColumn>=XN_ROWID && pExpr->iColumn<pTab->nCol );
+ continue;
+ }
+
+ /* 2nd case - a column reference with a COLLATE operator. Only match
+ ** of the COLLATE operator matches the collation of the column. */
+ if( pExpr->op==TK_COLLATE
+ && (pE2 = pExpr->pLeft)->op==TK_COLUMN
+ && pE2->iTable==pSrc->iCursor
+ ){
+ const char *zColl; /* The collating sequence name */
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
+ assert( pExpr->u.zToken!=0 );
+ assert( pE2->iColumn>=XN_ROWID && pE2->iColumn<pTab->nCol );
+ pExpr->iColumn = pE2->iColumn;
+ if( pE2->iColumn<0 ) continue; /* Collseq does not matter for rowid */
+ zColl = sqlcipher_sqlite3ColumnColl(&pTab->aCol[pE2->iColumn]);
+ if( zColl==0 ) zColl = sqlcipher_sqlite3StrBINARY;
+ if( sqlcipher_sqlite3_stricmp(pExpr->u.zToken, zColl)==0 ) continue;
+ }
+
+ /* No matches cause a break out of the loop */
+ break;
}
- if( i==n){
+ if( i==n ){
nOrderBy = n;
+ if( (pWInfo->wctrlFlags & WHERE_DISTINCTBY) ){
+ eDistinct = 2 + ((pWInfo->wctrlFlags & WHERE_SORTBYGROUP)!=0);
+ }else if( pWInfo->wctrlFlags & WHERE_GROUPBY ){
+ eDistinct = 1;
+ }
}
}
@@ -152037,46 +160648,35 @@ static sqlcipher_sqlite3_index_info *allocateIndexInfo(
*/
pIdxInfo = sqlcipher_sqlite3DbMallocZero(pParse->db, sizeof(*pIdxInfo)
+ (sizeof(*pIdxCons) + sizeof(*pUsage))*nTerm
- + sizeof(*pIdxOrderBy)*nOrderBy + sizeof(*pHidden) );
+ + sizeof(*pIdxOrderBy)*nOrderBy + sizeof(*pHidden)
+ + sizeof(sqlcipher_sqlite3_value*)*nTerm );
if( pIdxInfo==0 ){
sqlcipher_sqlite3ErrorMsg(pParse, "out of memory");
return 0;
}
pHidden = (struct HiddenIndexInfo*)&pIdxInfo[1];
- pIdxCons = (struct sqlcipher_sqlite3_index_constraint*)&pHidden[1];
+ pIdxCons = (struct sqlcipher_sqlite3_index_constraint*)&pHidden->aRhs[nTerm];
pIdxOrderBy = (struct sqlcipher_sqlite3_index_orderby*)&pIdxCons[nTerm];
pUsage = (struct sqlcipher_sqlite3_index_constraint_usage*)&pIdxOrderBy[nOrderBy];
- pIdxInfo->nOrderBy = nOrderBy;
pIdxInfo->aConstraint = pIdxCons;
pIdxInfo->aOrderBy = pIdxOrderBy;
pIdxInfo->aConstraintUsage = pUsage;
pHidden->pWC = pWC;
pHidden->pParse = pParse;
+ pHidden->eDistinct = eDistinct;
+ pHidden->mIn = 0;
for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
u16 op;
- if( pTerm->leftCursor != pSrc->iCursor ) continue;
- if( pTerm->prereqRight & mUnusable ) continue;
- assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) );
- testcase( pTerm->eOperator & WO_IN );
- testcase( pTerm->eOperator & WO_IS );
- testcase( pTerm->eOperator & WO_ISNULL );
- testcase( pTerm->eOperator & WO_ALL );
- if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue;
- if( pTerm->wtFlags & TERM_VNULL ) continue;
-
- /* tag-20191211-002: WHERE-clause constraints are not useful to the
- ** right-hand table of a LEFT JOIN. See tag-20191211-001 for the
- ** equivalent restriction for ordinary tables. */
- if( (pSrc->fg.jointype & JT_LEFT)!=0
- && !ExprHasProperty(pTerm->pExpr, EP_FromJoin)
- ){
- continue;
- }
- assert( pTerm->u.x.leftColumn>=(-1) );
+ if( (pTerm->wtFlags & TERM_OK)==0 ) continue;
pIdxCons[j].iColumn = pTerm->u.x.leftColumn;
pIdxCons[j].iTermOffset = i;
op = pTerm->eOperator & WO_ALL;
- if( op==WO_IN ) op = WO_EQ;
+ if( op==WO_IN ){
+ if( (pTerm->wtFlags & TERM_SLICE)==0 ){
+ pHidden->mIn |= SMASKBIT32(j);
+ }
+ op = WO_EQ;
+ }
if( op==WO_AUX ){
pIdxCons[j].op = pTerm->eMatchOp;
}else if( op & (WO_ISNULL|WO_IS) ){
@@ -152109,18 +160709,43 @@ static sqlcipher_sqlite3_index_info *allocateIndexInfo(
j++;
}
+ assert( j==nTerm );
pIdxInfo->nConstraint = j;
- for(i=0; i<nOrderBy; i++){
+ for(i=j=0; i<nOrderBy; i++){
Expr *pExpr = pOrderBy->a[i].pExpr;
- pIdxOrderBy[i].iColumn = pExpr->iColumn;
- pIdxOrderBy[i].desc = pOrderBy->a[i].sortFlags & KEYINFO_ORDER_DESC;
+ if( sqlcipher_sqlite3ExprIsConstant(pExpr) ) continue;
+ assert( pExpr->op==TK_COLUMN
+ || (pExpr->op==TK_COLLATE && pExpr->pLeft->op==TK_COLUMN
+ && pExpr->iColumn==pExpr->pLeft->iColumn) );
+ pIdxOrderBy[j].iColumn = pExpr->iColumn;
+ pIdxOrderBy[j].desc = pOrderBy->a[i].fg.sortFlags & KEYINFO_ORDER_DESC;
+ j++;
}
+ pIdxInfo->nOrderBy = j;
*pmNoOmit = mNoOmit;
return pIdxInfo;
}
/*
+** Free an sqlcipher_sqlite3_index_info structure allocated by allocateIndexInfo()
+** and possibly modified by xBestIndex methods.
+*/
+static void freeIndexInfo(sqlcipher_sqlite3 *db, sqlcipher_sqlite3_index_info *pIdxInfo){
+ HiddenIndexInfo *pHidden;
+ int i;
+ assert( pIdxInfo!=0 );
+ pHidden = (HiddenIndexInfo*)&pIdxInfo[1];
+ assert( pHidden->pParse!=0 );
+ assert( pHidden->pParse->db==db );
+ for(i=0; i<pIdxInfo->nConstraint; i++){
+ sqlcipher_sqlite3ValueFree(pHidden->aRhs[i]); /* IMP: R-14553-25174 */
+ pHidden->aRhs[i] = 0;
+ }
+ sqlcipher_sqlite3DbFree(db, pIdxInfo);
+}
+
+/*
** 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 sqlcipher_sqlite3_index_info object that
@@ -152141,7 +160766,9 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlcipher_sqlite3_index_inf
int rc;
whereTraceIndexInfoInputs(p);
+ pParse->db->nSchemaLock++;
rc = pVtab->pModule->xBestIndex(pVtab, p);
+ pParse->db->nSchemaLock--;
whereTraceIndexInfoOutputs(p);
if( rc!=SQLITE_OK && rc!=SQLITE_CONSTRAINT ){
@@ -152195,7 +160822,7 @@ static int whereKeyStats(
#endif
assert( pRec!=0 );
assert( pIdx->nSample>0 );
- assert( pRec->nField>0 && pRec->nField<=pIdx->nSampleCol );
+ assert( pRec->nField>0 );
/* Do a binary search to find the first sample greater than or equal
** to pRec. If pRec contains a single field, the set of samples to search
@@ -152241,7 +160868,7 @@ static int whereKeyStats(
** it is extended to two fields. The duplicates that this creates do not
** cause any problems.
*/
- nField = pRec->nField;
+ nField = MIN(pRec->nField, pIdx->nSample);
iCol = 0;
iSample = pIdx->nSample * nField;
do{
@@ -152832,9 +161459,10 @@ SQLITE_PRIVATE void sqlcipher_sqlite3WhereTermPrint(WhereTerm *pTerm, int iTerm)
memcpy(zType, "....", 5);
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';
+ if( ExprHasProperty(pTerm->pExpr, EP_OuterON) ) zType[2] = 'L';
if( pTerm->wtFlags & TERM_CODED ) zType[3] = 'C';
if( pTerm->eOperator & WO_SINGLE ){
+ assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 );
sqlcipher_sqlite3_snprintf(sizeof(zLeft),zLeft,"left={%d:%d}",
pTerm->leftCursor, pTerm->u.x.leftColumn);
}else if( (pTerm->eOperator & WO_OR)!=0 && pTerm->u.pOrInfo!=0 ){
@@ -152852,7 +161480,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3WhereTermPrint(WhereTerm *pTerm, int iTerm)
sqlcipher_sqlite3DebugPrintf(" prob=%-3d prereq=%llx,%llx",
pTerm->truthProb, (u64)pTerm->prereqAll, (u64)pTerm->prereqRight);
}
- if( pTerm->u.x.iField ){
+ if( (pTerm->eOperator & (WO_OR|WO_AND))==0 && pTerm->u.x.iField ){
sqlcipher_sqlite3DebugPrintf(" iField=%d", pTerm->u.x.iField);
}
if( pTerm->iParent>=0 ){
@@ -152883,7 +161511,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3WhereClausePrint(WhereClause *pWC){
SQLITE_PRIVATE void sqlcipher_sqlite3WhereLoopPrint(WhereLoop *p, WhereClause *pWC){
WhereInfo *pWInfo = pWC->pWInfo;
int nb = 1+(pWInfo->pTabList->nSrc+3)/4;
- struct SrcList_item *pItem = pWInfo->pTabList->a + p->iTab;
+ SrcItem *pItem = pWInfo->pTabList->a + p->iTab;
Table *pTab = pItem->pTab;
Bitmask mAll = (((Bitmask)1)<<(nb*4)) - 1;
sqlcipher_sqlite3DebugPrintf("%c%2d.%0*llx.%0*llx", p->cId,
@@ -152914,9 +161542,9 @@ SQLITE_PRIVATE void sqlcipher_sqlite3WhereLoopPrint(WhereLoop *p, WhereClause *p
sqlcipher_sqlite3_free(z);
}
if( p->wsFlags & WHERE_SKIPSCAN ){
- sqlcipher_sqlite3DebugPrintf(" f %05x %d-%d", p->wsFlags, p->nLTerm,p->nSkip);
+ sqlcipher_sqlite3DebugPrintf(" f %06x %d-%d", p->wsFlags, p->nLTerm,p->nSkip);
}else{
- sqlcipher_sqlite3DebugPrintf(" f %05x N %d", p->wsFlags, p->nLTerm);
+ sqlcipher_sqlite3DebugPrintf(" f %06x N %d", p->wsFlags, p->nLTerm);
}
sqlcipher_sqlite3DebugPrintf(" cost %d,%d,%d\n", p->rSetup, p->rRun, p->nOut);
if( p->nLTerm && (sqlcipher_sqlite3WhereTrace & 0x100)!=0 ){
@@ -152987,7 +161615,7 @@ static int whereLoopResize(sqlcipher_sqlite3 *db, WhereLoop *p, int n){
static int whereLoopXfer(sqlcipher_sqlite3 *db, WhereLoop *pTo, WhereLoop *pFrom){
whereLoopClearUnion(db, pTo);
if( whereLoopResize(db, pTo, pFrom->nLTerm) ){
- memset(&pTo->u, 0, sizeof(pTo->u));
+ memset(pTo, 0, WHERE_LOOP_XFER_SZ);
return SQLITE_NOMEM_BKPT;
}
memcpy(pTo, pFrom, WHERE_LOOP_XFER_SZ);
@@ -153012,14 +161640,7 @@ static void whereLoopDelete(sqlcipher_sqlite3 *db, WhereLoop *p){
** Free a WhereInfo structure
*/
static void whereInfoFree(sqlcipher_sqlite3 *db, WhereInfo *pWInfo){
- int i;
assert( pWInfo!=0 );
- for(i=0; i<pWInfo->nLevel; i++){
- WhereLevel *pLevel = &pWInfo->a[i];
- if( pLevel->pWLoop && (pLevel->pWLoop->wsFlags & WHERE_IN_ABLE) ){
- sqlcipher_sqlite3DbFree(db, pLevel->u.in.aInLoop);
- }
- }
sqlcipher_sqlite3WhereClauseClear(&pWInfo->sWC);
while( pWInfo->pLoops ){
WhereLoop *p = pWInfo->pLoops;
@@ -153027,13 +161648,30 @@ static void whereInfoFree(sqlcipher_sqlite3 *db, WhereInfo *pWInfo){
whereLoopDelete(db, p);
}
assert( pWInfo->pExprMods==0 );
+ while( pWInfo->pMemToFree ){
+ WhereMemBlock *pNext = pWInfo->pMemToFree->pNext;
+ sqlcipher_sqlite3DbFreeNN(db, pWInfo->pMemToFree);
+ pWInfo->pMemToFree = pNext;
+ }
sqlcipher_sqlite3DbFreeNN(db, pWInfo);
}
+/* Undo all Expr node modifications
+*/
+static void whereUndoExprMods(WhereInfo *pWInfo){
+ while( pWInfo->pExprMods ){
+ WhereExprMod *p = pWInfo->pExprMods;
+ pWInfo->pExprMods = p->pNext;
+ memcpy(p->pExpr, &p->orig, sizeof(p->orig));
+ sqlcipher_sqlite3DbFree(pWInfo->pParse->db, p);
+ }
+}
+
/*
** Return TRUE if all of the following are true:
**
-** (1) X has the same or lower cost that Y
+** (1) X has the same or lower cost, or returns the same or fewer rows,
+** than Y.
** (2) X uses fewer WHERE clause terms than Y
** (3) Every WHERE clause term used by X is also used by Y
** (4) X skips at least as many columns as Y
@@ -153056,11 +161694,8 @@ static int whereLoopCheaperProperSubset(
if( pX->nLTerm-pX->nSkip >= pY->nLTerm-pY->nSkip ){
return 0; /* X is not a subset of Y */
}
+ if( pX->rRun>pY->rRun && pX->nOut>pY->nOut ) return 0;
if( pY->nSkip > pX->nSkip ) return 0;
- 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--){
if( pX->aLTerm[i]==0 ) continue;
for(j=pY->nLTerm-1; j>=0; j--){
@@ -153076,8 +161711,8 @@ static int whereLoopCheaperProperSubset(
}
/*
-** Try to adjust the cost of WhereLoop pTemplate upwards or downwards so
-** that:
+** Try to adjust the cost and number of output rows of WhereLoop pTemplate
+** upwards or downwards so that:
**
** (1) pTemplate costs less than any other WhereLoops that are a proper
** subset of pTemplate
@@ -153098,16 +161733,20 @@ static void whereLoopAdjustCost(const WhereLoop *p, WhereLoop *pTemplate){
/* Adjust pTemplate cost downward so that it is cheaper than its
** subset p. */
WHERETRACE(0x80,("subset cost adjustment %d,%d to %d,%d\n",
- pTemplate->rRun, pTemplate->nOut, p->rRun, p->nOut-1));
- pTemplate->rRun = p->rRun;
- pTemplate->nOut = p->nOut - 1;
+ pTemplate->rRun, pTemplate->nOut,
+ MIN(p->rRun, pTemplate->rRun),
+ MIN(p->nOut - 1, pTemplate->nOut)));
+ pTemplate->rRun = MIN(p->rRun, pTemplate->rRun);
+ pTemplate->nOut = MIN(p->nOut - 1, pTemplate->nOut);
}else if( whereLoopCheaperProperSubset(pTemplate, p) ){
/* Adjust pTemplate cost upward so that it is costlier than p since
** pTemplate is a proper subset of p */
WHERETRACE(0x80,("subset cost adjustment %d,%d to %d,%d\n",
- pTemplate->rRun, pTemplate->nOut, p->rRun, p->nOut+1));
- pTemplate->rRun = p->rRun;
- pTemplate->nOut = p->nOut + 1;
+ pTemplate->rRun, pTemplate->nOut,
+ MAX(p->rRun, pTemplate->rRun),
+ MAX(p->nOut + 1, pTemplate->nOut)));
+ pTemplate->rRun = MAX(p->rRun, pTemplate->rRun);
+ pTemplate->nOut = MAX(p->nOut + 1, pTemplate->nOut);
}
}
}
@@ -153362,11 +162001,11 @@ static void whereLoopOutputAdjust(
LogEst iReduce = 0; /* pLoop->nOut should not exceed nRow-iReduce */
assert( (pLoop->wsFlags & WHERE_AUTO_INDEX)==0 );
- for(i=pWC->nTerm, pTerm=pWC->a; i>0; i--, pTerm++){
+ for(i=pWC->nBase, pTerm=pWC->a; i>0; i--, pTerm++){
assert( pTerm!=0 );
- if( (pTerm->wtFlags & TERM_VIRTUAL)!=0 ) break;
- if( (pTerm->prereqAll & pLoop->maskSelf)==0 ) continue;
if( (pTerm->prereqAll & notAllowed)!=0 ) continue;
+ if( (pTerm->prereqAll & pLoop->maskSelf)==0 ) continue;
+ if( (pTerm->wtFlags & TERM_VIRTUAL)!=0 ) continue;
for(j=pLoop->nLTerm-1; j>=0; j--){
pX = pLoop->aLTerm[j];
if( pX==0 ) continue;
@@ -153374,6 +162013,23 @@ static void whereLoopOutputAdjust(
if( pX->iParent>=0 && (&pWC->a[pX->iParent])==pTerm ) break;
}
if( j<0 ){
+ if( pLoop->maskSelf==pTerm->prereqAll ){
+ /* If there are extra terms in the WHERE clause not used by an index
+ ** that depend only on the table being scanned, and that will tend to
+ ** cause many rows to be omitted, then mark that table as
+ ** "self-culling".
+ **
+ ** 2022-03-24: Self-culling only applies if either the extra terms
+ ** are straight comparison operators that are non-true with NULL
+ ** operand, or if the loop is not an OUTER JOIN.
+ */
+ if( (pTerm->eOperator & 0x3f)!=0
+ || (pWC->pWInfo->pTabList->a[pLoop->iTab].fg.jointype
+ & (JT_LEFT|JT_LTORJ))==0
+ ){
+ pLoop->wsFlags |= WHERE_SELFCULL;
+ }
+ }
if( pTerm->truthProb<=0 ){
/* If a truth probability is specified using the likelihood() hints,
** then use the probability provided by the application. */
@@ -153401,7 +162057,9 @@ static void whereLoopOutputAdjust(
}
}
}
- if( pLoop->nOut > nRow-iReduce ) pLoop->nOut = nRow - iReduce;
+ if( pLoop->nOut > nRow-iReduce ){
+ pLoop->nOut = nRow - iReduce;
+ }
}
/*
@@ -153438,9 +162096,12 @@ static int whereRangeVectorLen(
char aff; /* Comparison affinity */
char idxaff = 0; /* Indexed columns affinity */
CollSeq *pColl; /* Comparison collation sequence */
- Expr *pLhs = pTerm->pExpr->pLeft->x.pList->a[i].pExpr;
- Expr *pRhs = pTerm->pExpr->pRight;
- if( pRhs->flags & EP_xIsSelect ){
+ Expr *pLhs, *pRhs;
+
+ assert( ExprUseXList(pTerm->pExpr->pLeft) );
+ pLhs = pTerm->pExpr->pLeft->x.pList->a[i].pExpr;
+ pRhs = pTerm->pExpr->pRight;
+ if( ExprUseXSelect(pRhs) ){
pRhs = pRhs->x.pSelect->pEList->a[i].pExpr;
}else{
pRhs = pRhs->x.pList->a[i].pExpr;
@@ -153494,7 +162155,7 @@ static int whereRangeVectorLen(
*/
static int whereLoopAddBtreeIndex(
WhereLoopBuilder *pBuilder, /* The WhereLoop factory */
- struct SrcList_item *pSrc, /* FROM clause term being analyzed */
+ SrcItem *pSrc, /* FROM clause term being analyzed */
Index *pProbe, /* An index on pSrc */
LogEst nInMul /* log(Number of iterations due to IN) */
){
@@ -153535,6 +162196,8 @@ static int whereLoopAddBtreeIndex(
if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE);
assert( pNew->u.btree.nEq<pProbe->nColumn );
+ assert( pNew->u.btree.nEq<pProbe->nKeyCol
+ || pProbe->idxType!=SQLITE_IDXTYPE_PRIMARYKEY );
saved_nEq = pNew->u.btree.nEq;
saved_nBtm = pNew->u.btree.nBtm;
@@ -153569,12 +162232,29 @@ static int whereLoopAddBtreeIndex(
if( pTerm->wtFlags & TERM_LIKEOPT && pTerm->eOperator==WO_LT ) continue;
/* tag-20191211-001: Do not allow constraints from the WHERE clause to
- ** be used by the right table of a LEFT JOIN. Only constraints in the
- ** ON clause are allowed. See tag-20191211-002 for the vtab equivalent. */
- if( (pSrc->fg.jointype & JT_LEFT)!=0
- && !ExprHasProperty(pTerm->pExpr, EP_FromJoin)
- ){
- continue;
+ ** be used by the right table of a LEFT JOIN nor by the left table of a
+ ** RIGHT JOIN. Only constraints in the ON clause are allowed.
+ ** See tag-20191211-002 for the vtab equivalent.
+ **
+ ** 2022-06-06: See https://sqlite.org/forum/forumpost/206d99a16dd9212f
+ ** for an example of a WHERE clause constraints that may not be used on
+ ** the right table of a RIGHT JOIN because the constraint implies a
+ ** not-NULL condition on the left table of the RIGHT JOIN.
+ **
+ ** 2022-06-10: The same condition applies to termCanDriveIndex() above.
+ ** https://sqlite.org/forum/forumpost/51e6959f61
+ */
+ if( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))!=0 ){
+ testcase( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))==JT_LEFT );
+ testcase( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))==JT_RIGHT );
+ testcase( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ|JT_RIGHT))==JT_LTORJ );
+ testcase( ExprHasProperty(pTerm->pExpr, EP_OuterON) )
+ testcase( ExprHasProperty(pTerm->pExpr, EP_InnerON) );
+ if( !ExprHasProperty(pTerm->pExpr, EP_OuterON|EP_InnerON)
+ || pTerm->pExpr->w.iJoin != pSrc->iCursor
+ ){
+ continue;
+ }
}
if( IsUniqueIndex(pProbe) && saved_nEq==pProbe->nKeyCol-1 ){
@@ -153599,7 +162279,7 @@ static int whereLoopAddBtreeIndex(
if( eOp & WO_IN ){
Expr *pExpr = pTerm->pExpr;
- if( ExprHasProperty(pExpr, EP_xIsSelect) ){
+ if( ExprUseXSelect(pExpr) ){
/* "x IN (SELECT ...)": TUNING: the SELECT returns 25 rows */
int i;
nIn = 46; assert( 46==sqlcipher_sqlite3LogEst(25) );
@@ -153617,7 +162297,7 @@ static int whereLoopAddBtreeIndex(
nIn = sqlcipher_sqlite3LogEst(pExpr->x.pList->nExpr);
}
if( pProbe->hasStat1 && rLogSize>=10 ){
- LogEst M, logK, safetyMargin;
+ LogEst M, logK, x;
/* Let:
** N = the total number of rows in the table
** K = the number of entries on the RHS of the IN operator
@@ -153640,16 +162320,25 @@ static int whereLoopAddBtreeIndex(
*/
M = pProbe->aiRowLogEst[saved_nEq];
logK = estLog(nIn);
- safetyMargin = 10; /* TUNING: extra weight for indexed IN */
- if( M + logK + safetyMargin < nIn + rLogSize ){
+ /* TUNING v----- 10 to bias toward indexed IN */
+ x = M + logK + 10 - (nIn + rLogSize);
+ if( x>=0 ){
+ WHERETRACE(0x40,
+ ("IN operator (N=%d M=%d logK=%d nIn=%d rLogSize=%d x=%d) "
+ "prefers indexed lookup\n",
+ saved_nEq, M, logK, nIn, rLogSize, x));
+ }else if( nInMul<2 && OptimizationEnabled(db, SQLITE_SeekScan) ){
WHERETRACE(0x40,
- ("Scan preferred over IN operator on column %d of \"%s\" (%d<%d)\n",
- saved_nEq, pProbe->zName, M+logK+10, nIn+rLogSize));
+ ("IN operator (N=%d M=%d logK=%d nIn=%d rLogSize=%d x=%d"
+ " nInMul=%d) prefers skip-scan\n",
+ saved_nEq, M, logK, nIn, rLogSize, x, nInMul));
pNew->wsFlags |= WHERE_IN_SEEKSCAN;
}else{
WHERETRACE(0x40,
- ("IN operator preferred on column %d of \"%s\" (%d>=%d)\n",
- saved_nEq, pProbe->zName, M+logK+10, nIn+rLogSize));
+ ("IN operator (N=%d M=%d logK=%d nIn=%d rLogSize=%d x=%d"
+ " nInMul=%d) prefers normal scan\n",
+ saved_nEq, M, logK, nIn, rLogSize, x, nInMul));
+ continue;
}
}
pNew->wsFlags |= WHERE_COLUMN_IN;
@@ -153668,6 +162357,7 @@ static int whereLoopAddBtreeIndex(
pNew->wsFlags |= WHERE_UNQ_WANTED;
}
}
+ if( scan.iEquiv>1 ) pNew->wsFlags |= WHERE_TRANSCONS;
}else if( eOp & WO_ISNULL ){
pNew->wsFlags |= WHERE_COLUMN_NULL;
}else if( eOp & (WO_GT|WO_GE) ){
@@ -153680,7 +162370,7 @@ static int whereLoopAddBtreeIndex(
pBtm = pTerm;
pTop = 0;
if( pTerm->wtFlags & TERM_LIKEOPT ){
- /* Range contraints that come from the LIKE optimization are
+ /* Range constraints that come from the LIKE optimization are
** always used in pairs. */
pTop = &pTerm[1];
assert( (pTop-(pTerm->pWC->a))<pTerm->pWC->nTerm );
@@ -153729,8 +162419,8 @@ static int whereLoopAddBtreeIndex(
tRowcnt nOut = 0;
if( nInMul==0
&& pProbe->nSample
- && pNew->u.btree.nEq<=pProbe->nSampleCol
- && ((eOp & WO_IN)==0 || !ExprHasProperty(pTerm->pExpr, EP_xIsSelect))
+ && ALWAYS(pNew->u.btree.nEq<=pProbe->nSampleCol)
+ && ((eOp & WO_IN)==0 || ExprUseXList(pTerm->pExpr))
&& OptimizationEnabled(db, SQLITE_Stat4)
){
Expr *pExpr = pTerm->pExpr;
@@ -153811,6 +162501,8 @@ static int whereLoopAddBtreeIndex(
if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0
&& pNew->u.btree.nEq<pProbe->nColumn
+ && (pNew->u.btree.nEq<pProbe->nKeyCol ||
+ pProbe->idxType!=SQLITE_IDXTYPE_PRIMARYKEY)
){
whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nInMul+nIn);
}
@@ -153914,24 +162606,28 @@ static int indexMightHelpWithOrderBy(
*/
static int whereUsablePartialIndex(
int iTab, /* The table for which we want an index */
- int isLeft, /* True if iTab is the right table of a LEFT JOIN */
+ u8 jointype, /* The JT_* flags on the join */
WhereClause *pWC, /* The WHERE clause of the query */
Expr *pWhere /* The WHERE clause from the partial index */
){
int i;
WhereTerm *pTerm;
- Parse *pParse = pWC->pWInfo->pParse;
+ Parse *pParse;
+
+ if( jointype & JT_LTORJ ) return 0;
+ pParse = pWC->pWInfo->pParse;
while( pWhere->op==TK_AND ){
- if( !whereUsablePartialIndex(iTab,isLeft,pWC,pWhere->pLeft) ) return 0;
+ if( !whereUsablePartialIndex(iTab,jointype,pWC,pWhere->pLeft) ) return 0;
pWhere = pWhere->pRight;
}
if( pParse->db->flags & SQLITE_EnableQPSG ) pParse = 0;
for(i=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
Expr *pExpr;
pExpr = pTerm->pExpr;
- if( (!ExprHasProperty(pExpr, EP_FromJoin) || pExpr->iRightJoinTable==iTab)
- && (isLeft==0 || ExprHasProperty(pExpr, EP_FromJoin))
+ if( (!ExprHasProperty(pExpr, EP_OuterON) || pExpr->w.iJoin==iTab)
+ && ((jointype & JT_OUTER)==0 || ExprHasProperty(pExpr, EP_OuterON))
&& sqlcipher_sqlite3ExprImpliesExpr(pParse, pExpr, pWhere, iTab)
+ && (pTerm->wtFlags & TERM_VNULL)==0
){
return 1;
}
@@ -153985,13 +162681,12 @@ static int whereLoopAddBtree(
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 */
+ SrcItem *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 */
@@ -154003,9 +162698,10 @@ static int whereLoopAddBtree(
pWC = pBuilder->pWC;
assert( !IsVirtual(pSrc->pTab) );
- if( pSrc->pIBIndex ){
+ if( pSrc->fg.isIndexedBy ){
+ assert( pSrc->fg.isCte==0 );
/* An INDEXED BY clause specifies a particular index to use */
- pProbe = pSrc->pIBIndex;
+ pProbe = pSrc->u2.pIBIndex;
}else if( !HasRowid(pTab) ){
pProbe = pTab->pIndex;
}else{
@@ -154034,22 +162730,24 @@ static int whereLoopAddBtree(
pProbe = &sPk;
}
rSize = pTab->nRowLogEst;
- rLogSize = estLog(rSize);
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
/* Automatic indexes */
if( !pBuilder->pOrSet /* Not part of an OR optimization */
- && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0
+ && (pWInfo->wctrlFlags & (WHERE_RIGHT_JOIN|WHERE_OR_SUBCLAUSE))==0
&& (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0
- && pSrc->pIBIndex==0 /* Has no INDEXED BY clause */
+ && !pSrc->fg.isIndexedBy /* Has no INDEXED BY clause */
&& !pSrc->fg.notIndexed /* Has no NOT INDEXED clause */
&& HasRowid(pTab) /* Not WITHOUT ROWID table. (FIXME: Why not?) */
&& !pSrc->fg.isCorrelated /* Not a correlated subquery */
&& !pSrc->fg.isRecursive /* Not a recursive common table expression. */
+ && (pSrc->fg.jointype & JT_RIGHT)==0 /* Not the right tab of a RIGHT JOIN */
){
/* Generate auto-index WhereLoops */
+ LogEst rLogSize; /* Logarithm of the number of rows in the table */
WhereTerm *pTerm;
WhereTerm *pWCEnd = pWC->a + pWC->nTerm;
+ rLogSize = estLog(rSize);
for(pTerm=pWC->a; rc==SQLITE_OK && pTerm<pWCEnd; pTerm++){
if( pTerm->prereqRight & pNew->maskSelf ) continue;
if( termCanDriveIndex(pTerm, pSrc, 0) ){
@@ -154067,7 +162765,7 @@ static int whereLoopAddBtree(
** those objects, since there is no opportunity to add schema
** indexes on subqueries and views. */
pNew->rSetup = rLogSize + rSize;
- if( pTab->pSelect==0 && (pTab->tabFlags & TF_Ephemeral)==0 ){
+ if( !IsView(pTab) && (pTab->tabFlags & TF_Ephemeral)==0 ){
pNew->rSetup += 28;
}else{
pNew->rSetup -= 10;
@@ -154091,11 +162789,10 @@ static int whereLoopAddBtree(
/* Loop over all indices. If there was an INDEXED BY clause, then only
** consider index pProbe. */
for(; rc==SQLITE_OK && pProbe;
- pProbe=(pSrc->pIBIndex ? 0 : pProbe->pNext), iSortIdx++
+ pProbe=(pSrc->fg.isIndexedBy ? 0 : pProbe->pNext), iSortIdx++
){
- int isLeft = (pSrc->fg.jointype & JT_OUTER)!=0;
if( pProbe->pPartIdxWhere!=0
- && !whereUsablePartialIndex(pSrc->iCursor, isLeft, pWC,
+ && !whereUsablePartialIndex(pSrc->iCursor, pSrc->fg.jointype, pWC,
pProbe->pPartIdxWhere)
){
testcase( pNew->iTab!=pSrc->iCursor ); /* See ticket [98d973b8f5] */
@@ -154203,7 +162900,14 @@ static int whereLoopAddBtree(
}
ApplyCostMultiplier(pNew->rRun, pTab->costMult);
whereLoopOutputAdjust(pWC, pNew, rSize);
- rc = whereLoopInsert(pBuilder, pNew);
+ if( (pSrc->fg.jointype & JT_RIGHT)!=0 && pProbe->aColExpr ){
+ /* Do not do an SCAN of a index-on-expression in a RIGHT JOIN
+ ** because the cursor used to access the index might not be
+ ** positioned to the correct row during the right-join no-match
+ ** loop. */
+ }else{
+ rc = whereLoopInsert(pBuilder, pNew);
+ }
pNew->nOut = rSize;
if( rc ) break;
}
@@ -154230,6 +162934,15 @@ static int whereLoopAddBtree(
#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
+** Return true if pTerm is a virtual table LIMIT or OFFSET term.
+*/
+static int isLimitTerm(WhereTerm *pTerm){
+ assert( pTerm->eOperator==WO_AUX || pTerm->eMatchOp==0 );
+ return pTerm->eMatchOp>=SQLITE_INDEX_CONSTRAINT_LIMIT
+ && pTerm->eMatchOp<=SQLITE_INDEX_CONSTRAINT_OFFSET;
+}
+
+/*
** Argument pIdxInfo is already populated with all constraints that may
** be used by the virtual table identified by pBuilder->pNew->iTab. This
** function marks a subset of those constraints usable, invokes the
@@ -154256,9 +162969,11 @@ static int whereLoopAddVirtualOne(
u16 mExclude, /* Exclude terms using these operators */
sqlcipher_sqlite3_index_info *pIdxInfo, /* Populated object for xBestIndex */
u16 mNoOmit, /* Do not omit these constraints */
- int *pbIn /* OUT: True if plan uses an IN(...) op */
+ int *pbIn, /* OUT: True if plan uses an IN(...) op */
+ int *pbRetryLimit /* OUT: Retry without LIMIT/OFFSET */
){
WhereClause *pWC = pBuilder->pWC;
+ HiddenIndexInfo *pHidden = (HiddenIndexInfo*)&pIdxInfo[1];
struct sqlcipher_sqlite3_index_constraint *pIdxCons;
struct sqlcipher_sqlite3_index_constraint_usage *pUsage = pIdxInfo->aConstraintUsage;
int i;
@@ -154266,7 +162981,7 @@ static int whereLoopAddVirtualOne(
int rc = SQLITE_OK;
WhereLoop *pNew = pBuilder->pNew;
Parse *pParse = pBuilder->pWInfo->pParse;
- struct SrcList_item *pSrc = &pBuilder->pWInfo->pTabList->a[pNew->iTab];
+ SrcItem *pSrc = &pBuilder->pWInfo->pTabList->a[pNew->iTab];
int nConstraint = pIdxInfo->nConstraint;
assert( (mUsable & mPrereq)==mPrereq );
@@ -154281,6 +162996,7 @@ static int whereLoopAddVirtualOne(
pIdxCons->usable = 0;
if( (pTerm->prereqRight & mUsable)==pTerm->prereqRight
&& (pTerm->eOperator & mExclude)==0
+ && (pbRetryLimit || !isLimitTerm(pTerm))
){
pIdxCons->usable = 1;
}
@@ -154296,6 +163012,7 @@ static int whereLoopAddVirtualOne(
pIdxInfo->estimatedRows = 25;
pIdxInfo->idxFlags = 0;
pIdxInfo->colUsed = (sqlcipher_sqlite3_int64)pSrc->colUsed;
+ pHidden->mHandleIn = 0;
/* Invoke the virtual table xBestIndex() method */
rc = vtabBestIndex(pParse, pSrc->pTab, pIdxInfo);
@@ -154313,8 +163030,8 @@ static int whereLoopAddVirtualOne(
mxTerm = -1;
assert( pNew->nLSlot>=nConstraint );
- for(i=0; i<nConstraint; i++) pNew->aLTerm[i] = 0;
- pNew->u.vtab.omitMask = 0;
+ memset(pNew->aLTerm, 0, sizeof(pNew->aLTerm[0])*nConstraint );
+ memset(&pNew->u.vtab, 0, sizeof(pNew->u.vtab));
pIdxCons = *(struct sqlcipher_sqlite3_index_constraint**)&pIdxInfo->aConstraint;
for(i=0; i<nConstraint; i++, pIdxCons++){
int iTerm;
@@ -154348,8 +163065,13 @@ static int whereLoopAddVirtualOne(
}else{
testcase( i!=iTerm );
}
+ if( pTerm->eMatchOp==SQLITE_INDEX_CONSTRAINT_OFFSET ){
+ pNew->u.vtab.bOmitOffset = 1;
+ }
}
- if( (pTerm->eOperator & WO_IN)!=0 ){
+ if( SMASKBIT32(i) & pHidden->mHandleIn ){
+ pNew->u.vtab.mHandleIn |= MASKBIT32(iTerm);
+ }else if( (pTerm->eOperator & WO_IN)!=0 ){
/* 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
@@ -154359,6 +163081,22 @@ static int whereLoopAddVirtualOne(
pIdxInfo->idxFlags &= ~SQLITE_INDEX_SCAN_UNIQUE;
*pbIn = 1; assert( (mExclude & WO_IN)==0 );
}
+
+ assert( pbRetryLimit || !isLimitTerm(pTerm) );
+ if( isLimitTerm(pTerm) && *pbIn ){
+ /* If there is an IN(...) term handled as an == (separate call to
+ ** xFilter for each value on the RHS of the IN) and a LIMIT or
+ ** OFFSET term handled as well, the plan is unusable. Set output
+ ** variable *pbRetryLimit to true to tell the caller to retry with
+ ** LIMIT and OFFSET disabled. */
+ if( pIdxInfo->needToFreeIdxStr ){
+ sqlcipher_sqlite3_free(pIdxInfo->idxStr);
+ pIdxInfo->idxStr = 0;
+ pIdxInfo->needToFreeIdxStr = 0;
+ }
+ *pbRetryLimit = 1;
+ return SQLITE_OK;
+ }
}
}
@@ -154403,11 +163141,19 @@ static int whereLoopAddVirtualOne(
}
/*
-** If this function is invoked from within an xBestIndex() callback, it
-** returns a pointer to a buffer containing the name of the collation
-** sequence associated with element iCons of the sqlcipher_sqlite3_index_info.aConstraint
-** array. Or, if iCons is out of range or there is no active xBestIndex
-** call, return NULL.
+** Return the collating sequence for a constraint passed into xBestIndex.
+**
+** pIdxInfo must be an sqlcipher_sqlite3_index_info structure passed into xBestIndex.
+** This routine depends on there being a HiddenIndexInfo structure immediately
+** following the sqlcipher_sqlite3_index_info structure.
+**
+** Return a pointer to the collation name:
+**
+** 1. If there is an explicit COLLATE operator on the constaint, return it.
+**
+** 2. Else, if the column has an alternative collation, return that.
+**
+** 3. Otherwise, return "BINARY".
*/
SQLITE_API const char *sqlcipher_sqlite3_vtab_collation(sqlcipher_sqlite3_index_info *pIdxInfo, int iCons){
HiddenIndexInfo *pHidden = (HiddenIndexInfo*)&pIdxInfo[1];
@@ -154425,6 +163171,97 @@ SQLITE_API const char *sqlcipher_sqlite3_vtab_collation(sqlcipher_sqlite3_index_
}
/*
+** Return true if constraint iCons is really an IN(...) constraint, or
+** false otherwise. If iCons is an IN(...) constraint, set (if bHandle!=0)
+** or clear (if bHandle==0) the flag to handle it using an iterator.
+*/
+SQLITE_API int sqlcipher_sqlite3_vtab_in(sqlcipher_sqlite3_index_info *pIdxInfo, int iCons, int bHandle){
+ HiddenIndexInfo *pHidden = (HiddenIndexInfo*)&pIdxInfo[1];
+ u32 m = SMASKBIT32(iCons);
+ if( m & pHidden->mIn ){
+ if( bHandle==0 ){
+ pHidden->mHandleIn &= ~m;
+ }else if( bHandle>0 ){
+ pHidden->mHandleIn |= m;
+ }
+ return 1;
+ }
+ return 0;
+}
+
+/*
+** This interface is callable from within the xBestIndex callback only.
+**
+** If possible, set (*ppVal) to point to an object containing the value
+** on the right-hand-side of constraint iCons.
+*/
+SQLITE_API int sqlcipher_sqlite3_vtab_rhs_value(
+ sqlcipher_sqlite3_index_info *pIdxInfo, /* Copy of first argument to xBestIndex */
+ int iCons, /* Constraint for which RHS is wanted */
+ sqlcipher_sqlite3_value **ppVal /* Write value extracted here */
+){
+ HiddenIndexInfo *pH = (HiddenIndexInfo*)&pIdxInfo[1];
+ sqlcipher_sqlite3_value *pVal = 0;
+ int rc = SQLITE_OK;
+ if( iCons<0 || iCons>=pIdxInfo->nConstraint ){
+ rc = SQLITE_MISUSE; /* EV: R-30545-25046 */
+ }else{
+ if( pH->aRhs[iCons]==0 ){
+ WhereTerm *pTerm = &pH->pWC->a[pIdxInfo->aConstraint[iCons].iTermOffset];
+ rc = sqlcipher_sqlite3ValueFromExpr(
+ pH->pParse->db, pTerm->pExpr->pRight, ENC(pH->pParse->db),
+ SQLITE_AFF_BLOB, &pH->aRhs[iCons]
+ );
+ testcase( rc!=SQLITE_OK );
+ }
+ pVal = pH->aRhs[iCons];
+ }
+ *ppVal = pVal;
+
+ if( rc==SQLITE_OK && pVal==0 ){ /* IMP: R-19933-32160 */
+ rc = SQLITE_NOTFOUND; /* IMP: R-36424-56542 */
+ }
+
+ return rc;
+}
+
+/*
+** Return true if ORDER BY clause may be handled as DISTINCT.
+*/
+SQLITE_API int sqlcipher_sqlite3_vtab_distinct(sqlcipher_sqlite3_index_info *pIdxInfo){
+ HiddenIndexInfo *pHidden = (HiddenIndexInfo*)&pIdxInfo[1];
+ assert( pHidden->eDistinct>=0 && pHidden->eDistinct<=3 );
+ return pHidden->eDistinct;
+}
+
+#if (defined(SQLITE_ENABLE_DBPAGE_VTAB) || defined(SQLITE_TEST)) \
+ && !defined(SQLITE_OMIT_VIRTUALTABLE)
+/*
+** Cause the prepared statement that is associated with a call to
+** xBestIndex to potentiall use all schemas. If the statement being
+** prepared is read-only, then just start read transactions on all
+** schemas. But if this is a write operation, start writes on all
+** schemas.
+**
+** This is used by the (built-in) sqlite_dbpage virtual table.
+*/
+SQLITE_PRIVATE void sqlcipher_sqlite3VtabUsesAllSchemas(sqlcipher_sqlite3_index_info *pIdxInfo){
+ HiddenIndexInfo *pHidden = (HiddenIndexInfo*)&pIdxInfo[1];
+ Parse *pParse = pHidden->pParse;
+ int nDb = pParse->db->nDb;
+ int i;
+ for(i=0; i<nDb; i++){
+ sqlcipher_sqlite3CodeVerifySchema(pParse, i);
+ }
+ if( pParse->writeMask ){
+ for(i=0; i<nDb; i++){
+ sqlcipher_sqlite3BeginWriteOperation(pParse, 0, i);
+ }
+ }
+}
+#endif
+
+/*
** Add all WhereLoop objects for a table of the join identified by
** pBuilder->pNew->iTab. That table is guaranteed to be a virtual table.
**
@@ -154458,13 +163295,14 @@ static int whereLoopAddVirtual(
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 */
+ SrcItem *pSrc; /* The FROM clause term to search */
sqlcipher_sqlite3_index_info *p; /* Object to pass to xBestIndex() */
int nConstraint; /* Number of constraints in p */
int bIn; /* True if plan uses IN(...) operator */
WhereLoop *pNew;
Bitmask mBest; /* Tables used by best possible plan */
u16 mNoOmit;
+ int bRetry = 0; /* True to retry with LIMIT/OFFSET disabled */
assert( (mPrereq & mUnusable)==0 );
pWInfo = pBuilder->pWInfo;
@@ -154473,8 +163311,7 @@ static int whereLoopAddVirtual(
pNew = pBuilder->pNew;
pSrc = &pWInfo->pTabList->a[pNew->iTab];
assert( IsVirtual(pSrc->pTab) );
- p = allocateIndexInfo(pParse, pWC, mUnusable, pSrc, pBuilder->pOrderBy,
- &mNoOmit);
+ p = allocateIndexInfo(pWInfo, pWC, mUnusable, pSrc, &mNoOmit);
if( p==0 ) return SQLITE_NOMEM_BKPT;
pNew->rSetup = 0;
pNew->wsFlags = WHERE_VIRTUALTABLE;
@@ -154482,14 +163319,22 @@ static int whereLoopAddVirtual(
pNew->u.vtab.needFree = 0;
nConstraint = p->nConstraint;
if( whereLoopResize(pParse->db, pNew, nConstraint) ){
- sqlcipher_sqlite3DbFree(pParse->db, p);
+ freeIndexInfo(pParse->db, p);
return SQLITE_NOMEM_BKPT;
}
/* First call xBestIndex() with all constraints usable. */
WHERETRACE(0x800, ("BEGIN %s.addVirtual()\n", pSrc->pTab->zName));
WHERETRACE(0x40, (" VirtualOne: all usable\n"));
- rc = whereLoopAddVirtualOne(pBuilder, mPrereq, ALLBITS, 0, p, mNoOmit, &bIn);
+ rc = whereLoopAddVirtualOne(
+ pBuilder, mPrereq, ALLBITS, 0, p, mNoOmit, &bIn, &bRetry
+ );
+ if( bRetry ){
+ assert( rc==SQLITE_OK );
+ rc = whereLoopAddVirtualOne(
+ pBuilder, mPrereq, ALLBITS, 0, p, mNoOmit, &bIn, 0
+ );
+ }
/* If the call to xBestIndex() with all terms enabled produced a plan
** that does not require any source tables (IOW: a plan with mBest==0)
@@ -154507,7 +163352,7 @@ static int whereLoopAddVirtual(
if( bIn ){
WHERETRACE(0x40, (" VirtualOne: all usable w/o IN\n"));
rc = whereLoopAddVirtualOne(
- pBuilder, mPrereq, ALLBITS, WO_IN, p, mNoOmit, &bIn);
+ pBuilder, mPrereq, ALLBITS, WO_IN, p, mNoOmit, &bIn, 0);
assert( bIn==0 );
mBestNoIn = pNew->prereq & ~mPrereq;
if( mBestNoIn==0 ){
@@ -154534,7 +163379,7 @@ static int whereLoopAddVirtual(
WHERETRACE(0x40, (" VirtualOne: mPrev=%04llx mNext=%04llx\n",
(sqlcipher_sqlite3_uint64)mPrev, (sqlcipher_sqlite3_uint64)mNext));
rc = whereLoopAddVirtualOne(
- pBuilder, mPrereq, mNext|mPrereq, 0, p, mNoOmit, &bIn);
+ pBuilder, mPrereq, mNext|mPrereq, 0, p, mNoOmit, &bIn, 0);
if( pNew->prereq==mPrereq ){
seenZero = 1;
if( bIn==0 ) seenZeroNoIN = 1;
@@ -154547,7 +163392,7 @@ static int whereLoopAddVirtual(
if( rc==SQLITE_OK && seenZero==0 ){
WHERETRACE(0x40, (" VirtualOne: all disabled\n"));
rc = whereLoopAddVirtualOne(
- pBuilder, mPrereq, mPrereq, 0, p, mNoOmit, &bIn);
+ pBuilder, mPrereq, mPrereq, 0, p, mNoOmit, &bIn, 0);
if( bIn==0 ) seenZeroNoIN = 1;
}
@@ -154557,12 +163402,12 @@ static int whereLoopAddVirtual(
if( rc==SQLITE_OK && seenZeroNoIN==0 ){
WHERETRACE(0x40, (" VirtualOne: all disabled and w/o IN\n"));
rc = whereLoopAddVirtualOne(
- pBuilder, mPrereq, mPrereq, WO_IN, p, mNoOmit, &bIn);
+ pBuilder, mPrereq, mPrereq, WO_IN, p, mNoOmit, &bIn, 0);
}
}
if( p->needToFreeIdxStr ) sqlcipher_sqlite3_free(p->idxStr);
- sqlcipher_sqlite3DbFreeNN(pParse->db, p);
+ freeIndexInfo(pParse->db, p);
WHERETRACE(0x800, ("END %s.addVirtual(), rc=%d\n", pSrc->pTab->zName, rc));
return rc;
}
@@ -154586,7 +163431,7 @@ static int whereLoopAddOr(
WhereClause tempWC;
WhereLoopBuilder sSubBuild;
WhereOrSet sSum, sCur;
- struct SrcList_item *pItem;
+ SrcItem *pItem;
pWC = pBuilder->pWC;
pWCEnd = pWC->a + pWC->nTerm;
@@ -154595,6 +163440,9 @@ static int whereLoopAddOr(
pItem = pWInfo->pTabList->a + pNew->iTab;
iCur = pItem->iCursor;
+ /* The multi-index OR optimization does not work for RIGHT and FULL JOIN */
+ if( pItem->fg.jointype & JT_RIGHT ) return SQLITE_OK;
+
for(pTerm=pWC->a; pTerm<pWCEnd && rc==SQLITE_OK; pTerm++){
if( (pTerm->eOperator & WO_OR)!=0
&& (pTerm->u.pOrInfo->indexable & pNew->maskSelf)!=0
@@ -154606,7 +163454,6 @@ static int whereLoopAddOr(
int i, j;
sSubBuild = *pBuilder;
- sSubBuild.pOrderBy = 0;
sSubBuild.pOrSet = &sCur;
WHERETRACE(0x200, ("Begin processing OR-clause %p\n", pTerm));
@@ -154618,6 +163465,7 @@ static int whereLoopAddOr(
tempWC.pOuter = pWC;
tempWC.op = TK_AND;
tempWC.nTerm = 1;
+ tempWC.nBase = 1;
tempWC.a = pOrTerm;
sSubBuild.pWC = &tempWC;
}else{
@@ -154642,7 +163490,9 @@ static int whereLoopAddOr(
if( rc==SQLITE_OK ){
rc = whereLoopAddOr(&sSubBuild, mPrereq, mUnusable);
}
- assert( rc==SQLITE_OK || rc==SQLITE_DONE || sCur.n==0 );
+ assert( rc==SQLITE_OK || rc==SQLITE_DONE || sCur.n==0
+ || rc==SQLITE_NOMEM );
+ testcase( rc==SQLITE_NOMEM && sCur.n>0 );
testcase( rc==SQLITE_DONE );
if( sCur.n==0 ){
sSum.n = 0;
@@ -154702,12 +163552,15 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
Bitmask mPrior = 0;
int iTab;
SrcList *pTabList = pWInfo->pTabList;
- struct SrcList_item *pItem;
- struct SrcList_item *pEnd = &pTabList->a[pWInfo->nLevel];
+ SrcItem *pItem;
+ SrcItem *pEnd = &pTabList->a[pWInfo->nLevel];
sqlcipher_sqlite3 *db = pWInfo->pParse->db;
int rc = SQLITE_OK;
+ int bFirstPastRJ = 0;
+ int hasRightJoin = 0;
WhereLoop *pNew;
+
/* Loop over the tables in the join, from left to right */
pNew = pBuilder->pNew;
whereLoopInit(pNew);
@@ -154717,18 +163570,30 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
pNew->iTab = iTab;
pBuilder->iPlanLimit += SQLITE_QUERY_PLANNER_LIMIT_INCR;
pNew->maskSelf = sqlcipher_sqlite3WhereGetMask(&pWInfo->sMaskSet, pItem->iCursor);
- if( (pItem->fg.jointype & (JT_LEFT|JT_CROSS))!=0 ){
- /* This condition is true when pItem is the FROM clause term on the
- ** right-hand-side of a LEFT or CROSS JOIN. */
- mPrereq = mPrior;
- }else{
+ if( bFirstPastRJ
+ || (pItem->fg.jointype & (JT_OUTER|JT_CROSS|JT_LTORJ))!=0
+ ){
+ /* Add prerequisites to prevent reordering of FROM clause terms
+ ** across CROSS joins and outer joins. The bFirstPastRJ boolean
+ ** prevents the right operand of a RIGHT JOIN from being swapped with
+ ** other elements even further to the right.
+ **
+ ** The JT_LTORJ case and the hasRightJoin flag work together to
+ ** prevent FROM-clause terms from moving from the right side of
+ ** a LEFT JOIN over to the left side of that join if the LEFT JOIN
+ ** is itself on the left side of a RIGHT JOIN.
+ */
+ if( pItem->fg.jointype & JT_LTORJ ) hasRightJoin = 1;
+ mPrereq |= mPrior;
+ bFirstPastRJ = (pItem->fg.jointype & JT_RIGHT)!=0;
+ }else if( !hasRightJoin ){
mPrereq = 0;
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( IsVirtual(pItem->pTab) ){
- struct SrcList_item *p;
+ SrcItem *p;
for(p=&pItem[1]; p<pEnd; p++){
- if( mUnusable || (p->fg.jointype & (JT_LEFT|JT_CROSS)) ){
+ if( mUnusable || (p->fg.jointype & (JT_OUTER|JT_CROSS)) ){
mUnusable |= sqlcipher_sqlite3WhereGetMask(&pWInfo->sMaskSet, p->iCursor);
}
}
@@ -154853,7 +163718,9 @@ static i8 wherePathSatisfiesOrderBy(
pLoop = pLast;
}
if( pLoop->wsFlags & WHERE_VIRTUALTABLE ){
- if( pLoop->u.vtab.isOrdered && (wctrlFlags & WHERE_DISTINCTBY)==0 ){
+ if( pLoop->u.vtab.isOrdered
+ && ((wctrlFlags&(WHERE_DISTINCTBY|WHERE_SORTBYGROUP))!=WHERE_DISTINCTBY)
+ ){
obSat = obDone;
}
break;
@@ -154871,7 +163738,7 @@ static i8 wherePathSatisfiesOrderBy(
if( MASKBIT(i) & obSat ) continue;
pOBExpr = sqlcipher_sqlite3ExprSkipCollateAndLikely(pOrderBy->a[i].pExpr);
if( NEVER(pOBExpr==0) ) continue;
- if( pOBExpr->op!=TK_COLUMN ) continue;
+ if( pOBExpr->op!=TK_COLUMN && pOBExpr->op!=TK_AGG_COLUMN ) continue;
if( pOBExpr->iTable!=iCur ) continue;
pTerm = sqlcipher_sqlite3WhereFindTerm(&pWInfo->sWC, iCur, pOBExpr->iColumn,
~ready, eqOpMask, 0);
@@ -154911,6 +163778,10 @@ static i8 wherePathSatisfiesOrderBy(
assert( nColumn==nKeyCol+1 || !HasRowid(pIndex->pTable) );
assert( pIndex->aiColumn[nColumn-1]==XN_ROWID
|| !HasRowid(pIndex->pTable));
+ /* All relevant terms of the index must also be non-NULL in order
+ ** for isOrderDistinct to be true. So the isOrderDistint value
+ ** computed here might be a false positive. Corrections will be
+ ** made at tag-20210426-1 below */
isOrderDistinct = IsUniqueIndex(pIndex)
&& (pLoop->wsFlags & WHERE_SKIPSCAN)==0;
}
@@ -154978,14 +163849,18 @@ static i8 wherePathSatisfiesOrderBy(
}
/* An unconstrained column that might be NULL means that this
- ** WhereLoop is not well-ordered
+ ** WhereLoop is not well-ordered. tag-20210426-1
*/
- if( isOrderDistinct
- && iColumn>=0
- && j>=pLoop->u.btree.nEq
- && pIndex->pTable->aCol[iColumn].notNull==0
- ){
- isOrderDistinct = 0;
+ if( isOrderDistinct ){
+ if( iColumn>=0
+ && j>=pLoop->u.btree.nEq
+ && pIndex->pTable->aCol[iColumn].notNull==0
+ ){
+ isOrderDistinct = 0;
+ }
+ if( iColumn==XN_EXPR ){
+ isOrderDistinct = 0;
+ }
}
/* Find the ORDER BY term that corresponds to the j-th column
@@ -155000,7 +163875,7 @@ static i8 wherePathSatisfiesOrderBy(
if( NEVER(pOBExpr==0) ) continue;
if( (wctrlFlags & (WHERE_GROUPBY|WHERE_DISTINCTBY))==0 ) bOnce = 0;
if( iColumn>=XN_ROWID ){
- if( pOBExpr->op!=TK_COLUMN ) continue;
+ if( pOBExpr->op!=TK_COLUMN && pOBExpr->op!=TK_AGG_COLUMN ) continue;
if( pOBExpr->iTable!=iCur ) continue;
if( pOBExpr->iColumn!=iColumn ) continue;
}else{
@@ -155023,16 +163898,18 @@ static i8 wherePathSatisfiesOrderBy(
/* 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].sortFlags&KEYINFO_ORDER_DESC) ){
+ if( (rev ^ revIdx)
+ != (pOrderBy->a[i].fg.sortFlags&KEYINFO_ORDER_DESC)
+ ){
isMatch = 0;
}
}else{
- rev = revIdx ^ (pOrderBy->a[i].sortFlags & KEYINFO_ORDER_DESC);
+ rev = revIdx ^ (pOrderBy->a[i].fg.sortFlags & KEYINFO_ORDER_DESC);
if( rev ) *pRevMask |= MASKBIT(iLoop);
revSet = 1;
}
}
- if( isMatch && (pOrderBy->a[i].sortFlags & KEYINFO_ORDER_BIGNULL) ){
+ if( isMatch && (pOrderBy->a[i].fg.sortFlags & KEYINFO_ORDER_BIGNULL) ){
if( j==pLoop->u.btree.nEq ){
pLoop->wsFlags |= WHERE_BIGNULL_SORT;
}else{
@@ -155079,7 +163956,7 @@ static i8 wherePathSatisfiesOrderBy(
if( obSat==obDone ) return (i8)nOrderBy;
if( !isOrderDistinct ){
for(i=nOrderBy-1; i>0; i--){
- Bitmask m = MASKBIT(i) - 1;
+ Bitmask m = ALWAYS(i<BMS) ? MASKBIT(i) - 1 : 0;
if( (obSat&m)==m ) return i;
}
return 0;
@@ -155112,7 +163989,7 @@ static i8 wherePathSatisfiesOrderBy(
** SELECT * FROM t1 GROUP BY y,x ORDER BY y,x; -- IsSorted()==0
*/
SQLITE_PRIVATE int sqlcipher_sqlite3WhereIsSorted(WhereInfo *pWInfo){
- assert( pWInfo->wctrlFlags & WHERE_GROUPBY );
+ assert( pWInfo->wctrlFlags & (WHERE_GROUPBY|WHERE_DISTINCTBY) );
assert( pWInfo->wctrlFlags & WHERE_SORTBYGROUP );
return pWInfo->sorted;
}
@@ -155169,7 +164046,7 @@ static LogEst whereSortingCost(
}else if( (pWInfo->wctrlFlags & WHERE_WANT_DISTINCT) ){
/* TUNING: In the sort for a DISTINCT operator, assume that the DISTINCT
** reduces the number of output rows by a factor of 2 */
- if( nRow>10 ) nRow -= 10; assert( 10==sqlcipher_sqlite3LogEst(2) );
+ if( nRow>10 ){ nRow -= 10; assert( 10==sqlcipher_sqlite3LogEst(2) ); }
}
rSortCost += estLog(nRow);
return rSortCost;
@@ -155513,12 +164390,12 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
}
pWInfo->bOrderedInnerLoop = 0;
if( pWInfo->pOrderBy ){
+ pWInfo->nOBSat = pFrom->isOrdered;
if( pWInfo->wctrlFlags & WHERE_DISTINCTBY ){
if( pFrom->isOrdered==pWInfo->pOrderBy->nExpr ){
pWInfo->eDistinct = WHERE_DISTINCT_ORDERED;
}
}else{
- pWInfo->nOBSat = pFrom->isOrdered;
pWInfo->revMask = pFrom->revLoop;
if( pWInfo->nOBSat<=0 ){
pWInfo->nOBSat = 0;
@@ -155581,7 +164458,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
*/
static int whereShortCut(WhereLoopBuilder *pBuilder){
WhereInfo *pWInfo;
- struct SrcList_item *pItem;
+ SrcItem *pItem;
WhereClause *pWC;
WhereTerm *pTerm;
WhereLoop *pLoop;
@@ -155589,6 +164466,7 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){
int j;
Table *pTab;
Index *pIdx;
+ WhereScan scan;
pWInfo = pBuilder->pWInfo;
if( pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE ) return 0;
@@ -155596,13 +164474,18 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){
pItem = pWInfo->pTabList->a;
pTab = pItem->pTab;
if( IsVirtual(pTab) ) return 0;
- if( pItem->fg.isIndexedBy ) return 0;
+ if( pItem->fg.isIndexedBy || pItem->fg.notIndexed ){
+ testcase( pItem->fg.isIndexedBy );
+ testcase( pItem->fg.notIndexed );
+ return 0;
+ }
iCur = pItem->iCursor;
pWC = &pWInfo->sWC;
pLoop = pBuilder->pNew;
pLoop->wsFlags = 0;
pLoop->nSkip = 0;
- pTerm = sqlcipher_sqlite3WhereFindTerm(pWC, iCur, -1, 0, WO_EQ|WO_IS, 0);
+ pTerm = whereScanInit(&scan, pWC, iCur, -1, WO_EQ|WO_IS, 0);
+ while( pTerm && pTerm->prereqRight ) pTerm = whereScanNext(&scan);
if( pTerm ){
testcase( pTerm->eOperator & WO_IS );
pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_IPK|WHERE_ONEROW;
@@ -155621,7 +164504,8 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){
) continue;
opMask = pIdx->uniqNotNull ? (WO_EQ|WO_IS) : WO_EQ;
for(j=0; j<pIdx->nKeyCol; j++){
- pTerm = sqlcipher_sqlite3WhereFindTerm(pWC, iCur, j, 0, opMask, pIdx);
+ pTerm = whereScanInit(&scan, pWC, iCur, j, opMask, pIdx);
+ while( pTerm && pTerm->prereqRight ) pTerm = whereScanNext(&scan);
if( pTerm==0 ) break;
testcase( pTerm->eOperator & WO_IS );
pLoop->aLTerm[j] = pTerm;
@@ -155650,9 +164534,15 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){
if( pWInfo->wctrlFlags & WHERE_WANT_DISTINCT ){
pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
}
+ if( scan.iEquiv>1 ) pLoop->wsFlags |= WHERE_TRANSCONS;
#ifdef SQLITE_DEBUG
pLoop->cId = '0';
#endif
+#ifdef WHERETRACE_ENABLED
+ if( sqlcipher_sqlite3WhereTrace ){
+ sqlcipher_sqlite3DebugPrintf("whereShortCut() used to compute solution\n");
+ }
+#endif
return 1;
}
return 0;
@@ -155706,6 +164596,150 @@ static void showAllWhereLoops(WhereInfo *pWInfo, WhereClause *pWC){
# define WHERETRACE_ALL_LOOPS(W,C)
#endif
+/* Attempt to omit tables from a join that do not affect the result.
+** For a table to not affect the result, the following must be true:
+**
+** 1) The query must not be an aggregate.
+** 2) The table must be the RHS of a LEFT JOIN.
+** 3) Either the query must be DISTINCT, or else the ON or USING clause
+** must contain a constraint that limits the scan of the table to
+** at most a single row.
+** 4) The table must not be referenced by any part of the query apart
+** from its own USING or ON clause.
+**
+** For example, given:
+**
+** CREATE TABLE t1(ipk INTEGER PRIMARY KEY, v1);
+** CREATE TABLE t2(ipk INTEGER PRIMARY KEY, v2);
+** CREATE TABLE t3(ipk INTEGER PRIMARY KEY, v3);
+**
+** then table t2 can be omitted from the following:
+**
+** SELECT v1, v3 FROM t1
+** LEFT JOIN t2 ON (t1.ipk=t2.ipk)
+** LEFT JOIN t3 ON (t1.ipk=t3.ipk)
+**
+** or from:
+**
+** SELECT DISTINCT v1, v3 FROM t1
+** LEFT JOIN t2
+** LEFT JOIN t3 ON (t1.ipk=t3.ipk)
+*/
+static SQLITE_NOINLINE Bitmask whereOmitNoopJoin(
+ WhereInfo *pWInfo,
+ Bitmask notReady
+){
+ int i;
+ Bitmask tabUsed;
+
+ /* Preconditions checked by the caller */
+ assert( pWInfo->nLevel>=2 );
+ assert( OptimizationEnabled(pWInfo->pParse->db, SQLITE_OmitNoopJoin) );
+
+ /* These two preconditions checked by the caller combine to guarantee
+ ** condition (1) of the header comment */
+ assert( pWInfo->pResultSet!=0 );
+ assert( 0==(pWInfo->wctrlFlags & WHERE_AGG_DISTINCT) );
+
+ tabUsed = sqlcipher_sqlite3WhereExprListUsage(&pWInfo->sMaskSet, pWInfo->pResultSet);
+ if( pWInfo->pOrderBy ){
+ tabUsed |= sqlcipher_sqlite3WhereExprListUsage(&pWInfo->sMaskSet, pWInfo->pOrderBy);
+ }
+ for(i=pWInfo->nLevel-1; i>=1; i--){
+ WhereTerm *pTerm, *pEnd;
+ SrcItem *pItem;
+ WhereLoop *pLoop;
+ pLoop = pWInfo->a[i].pWLoop;
+ pItem = &pWInfo->pTabList->a[pLoop->iTab];
+ if( (pItem->fg.jointype & (JT_LEFT|JT_RIGHT))!=JT_LEFT ) continue;
+ if( (pWInfo->wctrlFlags & WHERE_WANT_DISTINCT)==0
+ && (pLoop->wsFlags & WHERE_ONEROW)==0
+ ){
+ continue;
+ }
+ if( (tabUsed & pLoop->maskSelf)!=0 ) continue;
+ pEnd = pWInfo->sWC.a + pWInfo->sWC.nTerm;
+ for(pTerm=pWInfo->sWC.a; pTerm<pEnd; pTerm++){
+ if( (pTerm->prereqAll & pLoop->maskSelf)!=0 ){
+ if( !ExprHasProperty(pTerm->pExpr, EP_OuterON)
+ || pTerm->pExpr->w.iJoin!=pItem->iCursor
+ ){
+ break;
+ }
+ }
+ }
+ if( pTerm<pEnd ) continue;
+ WHERETRACE(0xffff, ("-> drop loop %c not used\n", pLoop->cId));
+ notReady &= ~pLoop->maskSelf;
+ for(pTerm=pWInfo->sWC.a; pTerm<pEnd; pTerm++){
+ if( (pTerm->prereqAll & pLoop->maskSelf)!=0 ){
+ pTerm->wtFlags |= TERM_CODED;
+ }
+ }
+ if( i!=pWInfo->nLevel-1 ){
+ int nByte = (pWInfo->nLevel-1-i) * sizeof(WhereLevel);
+ memmove(&pWInfo->a[i], &pWInfo->a[i+1], nByte);
+ }
+ pWInfo->nLevel--;
+ assert( pWInfo->nLevel>0 );
+ }
+ return notReady;
+}
+
+/*
+** Check to see if there are any SEARCH loops that might benefit from
+** using a Bloom filter. Consider a Bloom filter if:
+**
+** (1) The SEARCH happens more than N times where N is the number
+** of rows in the table that is being considered for the Bloom
+** filter.
+** (2) Some searches are expected to find zero rows. (This is determined
+** by the WHERE_SELFCULL flag on the term.)
+** (3) Bloom-filter processing is not disabled. (Checked by the
+** caller.)
+** (4) The size of the table being searched is known by ANALYZE.
+**
+** This block of code merely checks to see if a Bloom filter would be
+** appropriate, and if so sets the WHERE_BLOOMFILTER flag on the
+** WhereLoop. The implementation of the Bloom filter comes further
+** down where the code for each WhereLoop is generated.
+*/
+static SQLITE_NOINLINE void whereCheckIfBloomFilterIsUseful(
+ const WhereInfo *pWInfo
+){
+ int i;
+ LogEst nSearch;
+
+ assert( pWInfo->nLevel>=2 );
+ assert( OptimizationEnabled(pWInfo->pParse->db, SQLITE_BloomFilter) );
+ nSearch = pWInfo->a[0].pWLoop->nOut;
+ for(i=1; i<pWInfo->nLevel; i++){
+ WhereLoop *pLoop = pWInfo->a[i].pWLoop;
+ const unsigned int reqFlags = (WHERE_SELFCULL|WHERE_COLUMN_EQ);
+ if( (pLoop->wsFlags & reqFlags)==reqFlags
+ /* vvvvvv--- Always the case if WHERE_COLUMN_EQ is defined */
+ && ALWAYS((pLoop->wsFlags & (WHERE_IPK|WHERE_INDEXED))!=0)
+ ){
+ SrcItem *pItem = &pWInfo->pTabList->a[pLoop->iTab];
+ Table *pTab = pItem->pTab;
+ pTab->tabFlags |= TF_StatsUsed;
+ if( nSearch > pTab->nRowLogEst
+ && (pTab->tabFlags & TF_HasStat1)!=0
+ ){
+ testcase( pItem->fg.jointype & JT_LEFT );
+ pLoop->wsFlags |= WHERE_BLOOMFILTER;
+ pLoop->wsFlags &= ~WHERE_IDX_ONLY;
+ WHERETRACE(0xffff, (
+ "-> use Bloom-filter on loop %c because there are ~%.1e "
+ "lookups into %s which has only ~%.1e rows\n",
+ pLoop->cId, (double)sqlcipher_sqlite3LogEstToInt(nSearch), pTab->zName,
+ (double)sqlcipher_sqlite3LogEstToInt(pTab->nRowLogEst)));
+ }
+ }
+ nSearch += pLoop->nOut;
+ }
+}
+
/*
** Generate the beginning of the loop used for WHERE clause processing.
** The return value is a pointer to an opaque structure that contains
@@ -155800,6 +164834,7 @@ SQLITE_PRIVATE WhereInfo *sqlcipher_sqlite3WhereBegin(
Expr *pWhere, /* The WHERE clause */
ExprList *pOrderBy, /* An ORDER BY (or GROUP BY) clause, or NULL */
ExprList *pResultSet, /* Query result set. Req'd for DISTINCT */
+ Select *pLimit, /* Use this LIMIT/OFFSET clause, if any */
u16 wctrlFlags, /* The WHERE_* flags defined in sqliteInt.h */
int iAuxArg /* If WHERE_OR_SUBCLAUSE is set, index cursor number
** If WHERE_USE_LIMIT, then the limit amount */
@@ -155834,13 +164869,6 @@ SQLITE_PRIVATE WhereInfo *sqlcipher_sqlite3WhereBegin(
/* 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
- ** sqlcipher_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
@@ -155865,7 +164893,7 @@ SQLITE_PRIVATE WhereInfo *sqlcipher_sqlite3WhereBegin(
** field (type Bitmask) it must be aligned on an 8-byte boundary on
** some architectures. Hence the ROUND8() below.
*/
- nByteWInfo = ROUND8(sizeof(WhereInfo)+(nTabList-1)*sizeof(WhereLevel));
+ nByteWInfo = ROUND8P(sizeof(WhereInfo)+(nTabList-1)*sizeof(WhereLevel));
pWInfo = sqlcipher_sqlite3DbMallocRawNN(db, nByteWInfo + sizeof(WhereLoop));
if( db->mallocFailed ){
sqlcipher_sqlite3DbFree(db, pWInfo);
@@ -155883,11 +164911,18 @@ SQLITE_PRIVATE WhereInfo *sqlcipher_sqlite3WhereBegin(
pWInfo->wctrlFlags = wctrlFlags;
pWInfo->iLimit = iAuxArg;
pWInfo->savedNQueryLoop = pParse->nQueryLoop;
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ pWInfo->pLimit = pLimit;
+#endif
memset(&pWInfo->nOBSat, 0,
offsetof(WhereInfo,sWC) - offsetof(WhereInfo,nOBSat));
memset(&pWInfo->a[0], 0, sizeof(WhereLoop)+nTabList*sizeof(WhereLevel));
assert( pWInfo->eOnePass==ONEPASS_OFF ); /* ONEPASS defaults to OFF */
pMaskSet = &pWInfo->sMaskSet;
+ pMaskSet->n = 0;
+ pMaskSet->ix[0] = -99; /* Initialize ix[0] to a value that can never be
+ ** a valid cursor number, to avoid an initial
+ ** test for pMaskSet->n==0 in sqlcipher_sqlite3WhereGetMask() */
sWLB.pWInfo = pWInfo;
sWLB.pWC = &pWInfo->sWC;
sWLB.pNew = (WhereLoop*)(((char*)pWInfo)+nByteWInfo);
@@ -155900,7 +164935,6 @@ SQLITE_PRIVATE WhereInfo *sqlcipher_sqlite3WhereBegin(
/* Split the WHERE clause into separate subexpressions where each
** subexpression is separated by an AND operator.
*/
- initMaskSet(pMaskSet);
sqlcipher_sqlite3WhereClauseInit(&pWInfo->sWC, pWInfo);
sqlcipher_sqlite3WhereSplit(&pWInfo->sWC, pWhere, TK_AND);
@@ -155908,7 +164942,9 @@ SQLITE_PRIVATE WhereInfo *sqlcipher_sqlite3WhereBegin(
*/
if( nTabList==0 ){
if( pOrderBy ) pWInfo->nOBSat = pOrderBy->nExpr;
- if( wctrlFlags & WHERE_WANT_DISTINCT ){
+ if( (wctrlFlags & WHERE_WANT_DISTINCT)!=0
+ && OptimizationEnabled(db, SQLITE_DistinctOpt)
+ ){
pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
}
ExplainQueryPlan((pParse, 0, "SCAN CONSTANT ROW"));
@@ -155946,7 +164982,8 @@ SQLITE_PRIVATE WhereInfo *sqlcipher_sqlite3WhereBegin(
/* Analyze all of the subexpressions. */
sqlcipher_sqlite3WhereExprAnalyze(pTabList, &pWInfo->sWC);
- if( db->mallocFailed ) goto whereBeginError;
+ sqlcipher_sqlite3WhereAddLimit(&pWInfo->sWC, pLimit);
+ if( pParse->nErr ) goto whereBeginError;
/* Special case: WHERE terms that do not refer to any tables in the join
** (constant expressions). Evaluate each such term, and jump over all the
@@ -155959,7 +164996,7 @@ SQLITE_PRIVATE WhereInfo *sqlcipher_sqlite3WhereBegin(
** FROM ... WHERE random()>0; -- eval random() once per row
** FROM ... WHERE (SELECT random())>0; -- eval random() once overall
*/
- for(ii=0; ii<sWLB.pWC->nTerm; ii++){
+ for(ii=0; ii<sWLB.pWC->nBase; ii++){
WhereTerm *pT = &sWLB.pWC->a[ii];
if( pT->wtFlags & TERM_VIRTUAL ) continue;
if( pT->prereqAll==0 && (nTabList==0 || exprIsDeterministic(pT->pExpr)) ){
@@ -155969,7 +165006,12 @@ SQLITE_PRIVATE WhereInfo *sqlcipher_sqlite3WhereBegin(
}
if( wctrlFlags & WHERE_WANT_DISTINCT ){
- if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pResultSet) ){
+ if( OptimizationDisabled(db, SQLITE_DistinctOpt) ){
+ /* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via
+ ** sqlcipher_sqlite3_test_ctrl(SQLITE_TESTCTRL_OPTIMIZATIONS,...) */
+ wctrlFlags &= ~WHERE_WANT_DISTINCT;
+ pWInfo->wctrlFlags &= ~WHERE_WANT_DISTINCT;
+ }else if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pResultSet) ){
/* The DISTINCT marking is pointless. Ignore it. */
pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
}else if( pOrderBy==0 ){
@@ -156040,9 +165082,10 @@ SQLITE_PRIVATE WhereInfo *sqlcipher_sqlite3WhereBegin(
if( pWInfo->pOrderBy==0 && (db->flags & SQLITE_ReverseOrder)!=0 ){
pWInfo->revMask = ALLBITS;
}
- if( pParse->nErr || NEVER(db->mallocFailed) ){
+ if( pParse->nErr ){
goto whereBeginError;
}
+ assert( db->mallocFailed==0 );
#ifdef WHERETRACE_ENABLED
if( sqlcipher_sqlite3WhereTrace ){
sqlcipher_sqlite3DebugPrintf("---- Solution nRow=%d", pWInfo->nRowOut);
@@ -156070,83 +165113,36 @@ SQLITE_PRIVATE WhereInfo *sqlcipher_sqlite3WhereBegin(
}
#endif
- /* Attempt to omit tables from the join that do not affect the result.
- ** For a table to not affect the result, the following must be true:
- **
- ** 1) The query must not be an aggregate.
- ** 2) The table must be the RHS of a LEFT JOIN.
- ** 3) Either the query must be DISTINCT, or else the ON or USING clause
- ** must contain a constraint that limits the scan of the table to
- ** at most a single row.
- ** 4) The table must not be referenced by any part of the query apart
- ** from its own USING or ON clause.
- **
- ** For example, given:
- **
- ** CREATE TABLE t1(ipk INTEGER PRIMARY KEY, v1);
- ** CREATE TABLE t2(ipk INTEGER PRIMARY KEY, v2);
- ** CREATE TABLE t3(ipk INTEGER PRIMARY KEY, v3);
- **
- ** then table t2 can be omitted from the following:
- **
- ** SELECT v1, v3 FROM t1
- ** LEFT JOIN t2 ON (t1.ipk=t2.ipk)
- ** LEFT JOIN t3 ON (t1.ipk=t3.ipk)
+ /* Attempt to omit tables from a join that do not affect the result.
+ ** See the comment on whereOmitNoopJoin() for further information.
**
- ** or from:
- **
- ** SELECT DISTINCT v1, v3 FROM t1
- ** LEFT JOIN t2
- ** LEFT JOIN t3 ON (t1.ipk=t3.ipk)
+ ** This query optimization is factored out into a separate "no-inline"
+ ** procedure to keep the sqlcipher_sqlite3WhereBegin() procedure from becoming
+ ** too large. If sqlcipher_sqlite3WhereBegin() becomes too large, that prevents
+ ** some C-compiler optimizers from in-lining the
+ ** sqlcipher_sqlite3WhereCodeOneLoopStart() procedure, and it is important to
+ ** in-line sqlcipher_sqlite3WhereCodeOneLoopStart() for performance reasons.
*/
notReady = ~(Bitmask)0;
if( pWInfo->nLevel>=2
- && pResultSet!=0 /* guarantees condition (1) above */
+ && pResultSet!=0 /* these two combine to guarantee */
+ && 0==(wctrlFlags & WHERE_AGG_DISTINCT) /* condition (1) above */
&& OptimizationEnabled(db, SQLITE_OmitNoopJoin)
){
- int i;
- Bitmask tabUsed = sqlcipher_sqlite3WhereExprListUsage(pMaskSet, pResultSet);
- if( sWLB.pOrderBy ){
- tabUsed |= sqlcipher_sqlite3WhereExprListUsage(pMaskSet, sWLB.pOrderBy);
- }
- for(i=pWInfo->nLevel-1; i>=1; i--){
- WhereTerm *pTerm, *pEnd;
- struct SrcList_item *pItem;
- pLoop = pWInfo->a[i].pWLoop;
- pItem = &pWInfo->pTabList->a[pLoop->iTab];
- if( (pItem->fg.jointype & JT_LEFT)==0 ) continue;
- if( (wctrlFlags & WHERE_WANT_DISTINCT)==0
- && (pLoop->wsFlags & WHERE_ONEROW)==0
- ){
- continue;
- }
- if( (tabUsed & pLoop->maskSelf)!=0 ) continue;
- pEnd = sWLB.pWC->a + sWLB.pWC->nTerm;
- for(pTerm=sWLB.pWC->a; pTerm<pEnd; pTerm++){
- if( (pTerm->prereqAll & pLoop->maskSelf)!=0 ){
- if( !ExprHasProperty(pTerm->pExpr, EP_FromJoin)
- || pTerm->pExpr->iRightJoinTable!=pItem->iCursor
- ){
- break;
- }
- }
- }
- if( pTerm<pEnd ) continue;
- WHERETRACE(0xffff, ("-> drop loop %c not used\n", pLoop->cId));
- notReady &= ~pLoop->maskSelf;
- for(pTerm=sWLB.pWC->a; pTerm<pEnd; pTerm++){
- if( (pTerm->prereqAll & pLoop->maskSelf)!=0 ){
- pTerm->wtFlags |= TERM_CODED;
- }
- }
- if( i!=pWInfo->nLevel-1 ){
- int nByte = (pWInfo->nLevel-1-i) * sizeof(WhereLevel);
- memmove(&pWInfo->a[i], &pWInfo->a[i+1], nByte);
- }
- pWInfo->nLevel--;
- nTabList--;
- }
+ notReady = whereOmitNoopJoin(pWInfo, notReady);
+ nTabList = pWInfo->nLevel;
+ assert( nTabList>0 );
}
+
+ /* Check to see if there are any SEARCH loops that might benefit from
+ ** using a Bloom filter.
+ */
+ if( pWInfo->nLevel>=2
+ && OptimizationEnabled(db, SQLITE_BloomFilter)
+ ){
+ whereCheckIfBloomFilterIsUseful(pWInfo);
+ }
+
#if defined(WHERETRACE_ENABLED)
if( sqlcipher_sqlite3WhereTrace & 0x100 ){ /* Display all terms of the WHERE clause */
sqlcipher_sqlite3DebugPrintf("---- WHERE clause at end of analysis:\n");
@@ -156201,13 +165197,13 @@ SQLITE_PRIVATE WhereInfo *sqlcipher_sqlite3WhereBegin(
for(ii=0, pLevel=pWInfo->a; ii<nTabList; ii++, pLevel++){
Table *pTab; /* Table to open */
int iDb; /* Index of database containing table/index */
- struct SrcList_item *pTabItem;
+ SrcItem *pTabItem;
pTabItem = &pTabList->a[pLevel->iFrom];
pTab = pTabItem->pTab;
iDb = sqlcipher_sqlite3SchemaToIndex(db, pTab->pSchema);
pLoop = pLevel->pWLoop;
- if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ){
+ if( (pTab->tabFlags & TF_Ephemeral)!=0 || IsView(pTab) ){
/* Do nothing */
}else
#ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -156219,8 +165215,10 @@ SQLITE_PRIVATE WhereInfo *sqlcipher_sqlite3WhereBegin(
/* noop */
}else
#endif
- if( (pLoop->wsFlags & WHERE_IDX_ONLY)==0
- && (wctrlFlags & WHERE_OR_SUBCLAUSE)==0 ){
+ if( ((pLoop->wsFlags & WHERE_IDX_ONLY)==0
+ && (wctrlFlags & WHERE_OR_SUBCLAUSE)==0)
+ || (pTabItem->fg.jointype & (JT_LTORJ|JT_RIGHT))!=0
+ ){
int op = OP_OpenRead;
if( pWInfo->eOnePass!=ONEPASS_OFF ){
op = OP_OpenWrite;
@@ -156233,6 +165231,7 @@ SQLITE_PRIVATE WhereInfo *sqlcipher_sqlite3WhereBegin(
if( pWInfo->eOnePass==ONEPASS_OFF
&& pTab->nCol<BMS
&& (pTab->tabFlags & (TF_HasGenerated|TF_WithoutRowid))==0
+ && (pLoop->wsFlags & (WHERE_AUTO_INDEX|WHERE_BLOOMFILTER))==0
){
/* If we know that only a prefix of the record will be used,
** it is advantageous to reduce the "column count" field in
@@ -156288,6 +165287,7 @@ SQLITE_PRIVATE WhereInfo *sqlcipher_sqlite3WhereBegin(
iIndexCur = pParse->nTab++;
}
pLevel->iIdxCur = iIndexCur;
+ assert( pIx!=0 );
assert( pIx->pSchema==pTab->pSchema );
assert( iIndexCur>=0 );
if( op ){
@@ -156321,6 +165321,37 @@ SQLITE_PRIVATE WhereInfo *sqlcipher_sqlite3WhereBegin(
}
}
if( iDb>=0 ) sqlcipher_sqlite3CodeVerifySchema(pParse, iDb);
+ if( (pTabItem->fg.jointype & JT_RIGHT)!=0
+ && (pLevel->pRJ = sqlcipher_sqlite3WhereMalloc(pWInfo, sizeof(WhereRightJoin)))!=0
+ ){
+ WhereRightJoin *pRJ = pLevel->pRJ;
+ pRJ->iMatch = pParse->nTab++;
+ pRJ->regBloom = ++pParse->nMem;
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_Blob, 65536, pRJ->regBloom);
+ pRJ->regReturn = ++pParse->nMem;
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_Null, 0, pRJ->regReturn);
+ assert( pTab==pTabItem->pTab );
+ if( HasRowid(pTab) ){
+ KeyInfo *pInfo;
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pRJ->iMatch, 1);
+ pInfo = sqlcipher_sqlite3KeyInfoAlloc(pParse->db, 1, 0);
+ if( pInfo ){
+ pInfo->aColl[0] = 0;
+ pInfo->aSortFlags[0] = 0;
+ sqlcipher_sqlite3VdbeAppendP4(v, pInfo, P4_KEYINFO);
+ }
+ }else{
+ Index *pPk = sqlcipher_sqlite3PrimaryKeyIndex(pTab);
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pRJ->iMatch, pPk->nKeyCol);
+ sqlcipher_sqlite3VdbeSetP4KeyInfo(pParse, pPk);
+ }
+ pLoop->wsFlags &= ~WHERE_IDX_ONLY;
+ /* The nature of RIGHT JOIN processing is such that it messes up
+ ** the output order. So omit any ORDER BY/GROUP BY elimination
+ ** optimizations. We need to do an actual sort for RIGHT JOIN. */
+ pWInfo->nOBSat = 0;
+ pWInfo->eDistinct = WHERE_DISTINCT_UNORDERED;
+ }
}
pWInfo->iTop = sqlcipher_sqlite3VdbeCurrentAddr(v);
if( db->mallocFailed ) goto whereBeginError;
@@ -156332,15 +165363,31 @@ SQLITE_PRIVATE WhereInfo *sqlcipher_sqlite3WhereBegin(
for(ii=0; ii<nTabList; ii++){
int addrExplain;
int wsFlags;
+ SrcItem *pSrc;
+ if( pParse->nErr ) goto whereBeginError;
pLevel = &pWInfo->a[ii];
wsFlags = pLevel->pWLoop->wsFlags;
+ pSrc = &pTabList->a[pLevel->iFrom];
+ if( pSrc->fg.isMaterialized ){
+ if( pSrc->fg.isCorrelated ){
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_Gosub, pSrc->regReturn, pSrc->addrFillSub);
+ }else{
+ int iOnce = sqlcipher_sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_Gosub, pSrc->regReturn, pSrc->addrFillSub);
+ sqlcipher_sqlite3VdbeJumpHere(v, iOnce);
+ }
+ }
+ if( (wsFlags & (WHERE_AUTO_INDEX|WHERE_BLOOMFILTER))!=0 ){
+ if( (wsFlags & WHERE_AUTO_INDEX)!=0 ){
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
- if( (pLevel->pWLoop->wsFlags & WHERE_AUTO_INDEX)!=0 ){
- constructAutomaticIndex(pParse, &pWInfo->sWC,
- &pTabList->a[pLevel->iFrom], notReady, pLevel);
+ constructAutomaticIndex(pParse, &pWInfo->sWC,
+ &pTabList->a[pLevel->iFrom], notReady, pLevel);
+#endif
+ }else{
+ sqlcipher_sqlite3ConstructBloomFilter(pWInfo, ii, pLevel, notReady);
+ }
if( db->mallocFailed ) goto whereBeginError;
}
-#endif
addrExplain = sqlcipher_sqlite3WhereExplainOneScan(
pParse, pTabList, pLevel, wctrlFlags
);
@@ -156360,6 +165407,8 @@ SQLITE_PRIVATE WhereInfo *sqlcipher_sqlite3WhereBegin(
/* Jump here if malloc fails */
whereBeginError:
if( pWInfo ){
+ testcase( pWInfo->pExprMods!=0 );
+ whereUndoExprMods(pWInfo);
pParse->nQueryLoop = pWInfo->savedNQueryLoop;
whereInfoFree(db, pWInfo);
}
@@ -156386,6 +165435,26 @@ whereBeginError:
}
#endif
+#ifdef SQLITE_DEBUG
+/*
+** Return true if cursor iCur is opened by instruction k of the
+** bytecode. Used inside of assert() only.
+*/
+static int cursorIsOpen(Vdbe *v, int iCur, int k){
+ while( k>=0 ){
+ VdbeOp *pOp = sqlcipher_sqlite3VdbeGetOp(v,k--);
+ if( pOp->p1!=iCur ) continue;
+ if( pOp->opcode==OP_Close ) return 0;
+ if( pOp->opcode==OP_OpenRead ) return 1;
+ if( pOp->opcode==OP_OpenWrite ) return 1;
+ if( pOp->opcode==OP_OpenDup ) return 1;
+ if( pOp->opcode==OP_OpenAutoindex ) return 1;
+ if( pOp->opcode==OP_OpenEphemeral ) return 1;
+ }
+ return 0;
+}
+#endif /* SQLITE_DEBUG */
+
/*
** Generate the end of the WHERE loop. See comments on
** sqlcipher_sqlite3WhereBegin() for additional information.
@@ -156399,6 +165468,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3WhereEnd(WhereInfo *pWInfo){
SrcList *pTabList = pWInfo->pTabList;
sqlcipher_sqlite3 *db = pParse->db;
int iEnd = sqlcipher_sqlite3VdbeCurrentAddr(v);
+ int nRJ = 0;
/* Generate loop termination code.
*/
@@ -156406,6 +165476,17 @@ SQLITE_PRIVATE void sqlcipher_sqlite3WhereEnd(WhereInfo *pWInfo){
for(i=pWInfo->nLevel-1; i>=0; i--){
int addr;
pLevel = &pWInfo->a[i];
+ if( pLevel->pRJ ){
+ /* Terminate the subroutine that forms the interior of the loop of
+ ** the RIGHT JOIN table */
+ WhereRightJoin *pRJ = pLevel->pRJ;
+ sqlcipher_sqlite3VdbeResolveLabel(v, pLevel->addrCont);
+ pLevel->addrCont = 0;
+ pRJ->endSubrtn = sqlcipher_sqlite3VdbeCurrentAddr(v);
+ sqlcipher_sqlite3VdbeAddOp3(v, OP_Return, pRJ->regReturn, pRJ->addrSubrtn, 1);
+ VdbeCoverage(v);
+ nRJ++;
+ }
pLoop = pLevel->pWLoop;
if( pLevel->op!=OP_Noop ){
#ifndef SQLITE_DISABLE_SKIPAHEAD_DISTINCT
@@ -156433,7 +165514,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3WhereEnd(WhereInfo *pWInfo){
}
#endif /* SQLITE_DISABLE_SKIPAHEAD_DISTINCT */
/* The common case: Advance to the next row */
- sqlcipher_sqlite3VdbeResolveLabel(v, pLevel->addrCont);
+ if( pLevel->addrCont ) sqlcipher_sqlite3VdbeResolveLabel(v, pLevel->addrCont);
sqlcipher_sqlite3VdbeAddOp3(v, pLevel->op, pLevel->p1, pLevel->p2, pLevel->p3);
sqlcipher_sqlite3VdbeChangeP5(v, pLevel->p5);
VdbeCoverage(v);
@@ -156448,14 +165529,16 @@ SQLITE_PRIVATE void sqlcipher_sqlite3WhereEnd(WhereInfo *pWInfo){
#ifndef SQLITE_DISABLE_SKIPAHEAD_DISTINCT
if( addrSeek ) sqlcipher_sqlite3VdbeJumpHere(v, addrSeek);
#endif
- }else{
+ }else if( pLevel->addrCont ){
sqlcipher_sqlite3VdbeResolveLabel(v, pLevel->addrCont);
}
- if( pLoop->wsFlags & WHERE_IN_ABLE && pLevel->u.in.nIn>0 ){
+ if( (pLoop->wsFlags & WHERE_IN_ABLE)!=0 && pLevel->u.in.nIn>0 ){
struct InLoop *pIn;
int j;
sqlcipher_sqlite3VdbeResolveLabel(v, pLevel->addrNxt);
for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){
+ assert( sqlcipher_sqlite3VdbeGetOp(v, pIn->addrInTop+1)->opcode==OP_IsNull
+ || pParse->db->mallocFailed );
sqlcipher_sqlite3VdbeJumpHere(v, pIn->addrInTop+1);
if( pIn->eEndLoopOp!=OP_Noop ){
if( pIn->nPrefix ){
@@ -156480,6 +165563,11 @@ SQLITE_PRIVATE void sqlcipher_sqlite3WhereEnd(WhereInfo *pWInfo){
sqlcipher_sqlite3VdbeCurrentAddr(v)+2,
pIn->iBase, pIn->nPrefix);
VdbeCoverage(v);
+ /* Retarget the OP_IsNull against the left operand of IN so
+ ** it jumps past the OP_IfNoHope. This is because the
+ ** OP_IsNull also bypasses the OP_Affinity opcode that is
+ ** required by OP_IfNoHope. */
+ sqlcipher_sqlite3VdbeJumpHere(v, pIn->addrInTop+1);
}
}
sqlcipher_sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop);
@@ -156491,6 +165579,10 @@ SQLITE_PRIVATE void sqlcipher_sqlite3WhereEnd(WhereInfo *pWInfo){
}
}
sqlcipher_sqlite3VdbeResolveLabel(v, pLevel->addrBrk);
+ if( pLevel->pRJ ){
+ sqlcipher_sqlite3VdbeAddOp3(v, OP_Return, pLevel->pRJ->regReturn, 0, 1);
+ VdbeCoverage(v);
+ }
if( pLevel->addrSkip ){
sqlcipher_sqlite3VdbeGoto(v, pLevel->addrSkip);
VdbeComment((v, "next skip-scan on %s", pLoop->u.btree.pIndex->zName));
@@ -156513,8 +165605,14 @@ SQLITE_PRIVATE void sqlcipher_sqlite3WhereEnd(WhereInfo *pWInfo){
sqlcipher_sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iTabCur);
}
if( (ws & WHERE_INDEXED)
- || ((ws & WHERE_MULTI_OR) && pLevel->u.pCovidx)
+ || ((ws & WHERE_MULTI_OR) && pLevel->u.pCoveringIdx)
){
+ if( ws & WHERE_MULTI_OR ){
+ Index *pIx = pLevel->u.pCoveringIdx;
+ int iDb = sqlcipher_sqlite3SchemaToIndex(db, pIx->pSchema);
+ sqlcipher_sqlite3VdbeAddOp3(v, OP_ReopenIdx, pLevel->iIdxCur, pIx->tnum, iDb);
+ sqlcipher_sqlite3VdbeSetP4KeyInfo(pParse, pIx);
+ }
sqlcipher_sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur);
}
if( pLevel->op==OP_Return ){
@@ -156528,21 +165626,26 @@ SQLITE_PRIVATE void sqlcipher_sqlite3WhereEnd(WhereInfo *pWInfo){
pWInfo->pTabList->a[pLevel->iFrom].pTab->zName));
}
- /* The "break" point is here, just past the end of the outer loop.
- ** Set it.
- */
- sqlcipher_sqlite3VdbeResolveLabel(v, pWInfo->iBreak);
-
assert( pWInfo->nLevel<=pTabList->nSrc );
+ if( pWInfo->pExprMods ) whereUndoExprMods(pWInfo);
for(i=0, pLevel=pWInfo->a; i<pWInfo->nLevel; i++, pLevel++){
int k, last;
VdbeOp *pOp, *pLastOp;
Index *pIdx = 0;
- struct SrcList_item *pTabItem = &pTabList->a[pLevel->iFrom];
+ SrcItem *pTabItem = &pTabList->a[pLevel->iFrom];
Table *pTab = pTabItem->pTab;
assert( pTab!=0 );
pLoop = pLevel->pWLoop;
+ /* Do RIGHT JOIN processing. Generate code that will output the
+ ** unmatched rows of the right operand of the RIGHT JOIN with
+ ** all of the columns of the left operand set to NULL.
+ */
+ if( pLevel->pRJ ){
+ sqlcipher_sqlite3WhereRightJoinLoop(pWInfo, i, pLevel);
+ continue;
+ }
+
/* For a co-routine, change all OP_Column references to the table of
** the co-routine into OP_Copy of result contained in a register.
** OP_Rowid becomes OP_Null.
@@ -156554,29 +165657,6 @@ SQLITE_PRIVATE void sqlcipher_sqlite3WhereEnd(WhereInfo *pWInfo){
continue;
}
-#ifdef SQLITE_ENABLE_EARLY_CURSOR_CLOSE
- /* Close all of the cursors that were opened by sqlcipher_sqlite3WhereBegin.
- ** Except, do not close cursors that will be reused by the OR optimization
- ** (WHERE_OR_SUBCLAUSE). 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_OR_SUBCLAUSE)==0
- ){
- int ws = pLoop->wsFlags;
- if( pWInfo->eOnePass==ONEPASS_OFF && (ws & WHERE_IDX_ONLY)==0 ){
- sqlcipher_sqlite3VdbeAddOp1(v, OP_Close, pTabItem->iCursor);
- }
- if( (ws & WHERE_INDEXED)!=0
- && (ws & (WHERE_IPK|WHERE_AUTO_INDEX))==0
- && pLevel->iIdxCur!=pWInfo->aiCurOnePass[1]
- ){
- sqlcipher_sqlite3VdbeAddOp1(v, OP_Close, pLevel->iIdxCur);
- }
- }
-#endif
-
/* 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
@@ -156591,7 +165671,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3WhereEnd(WhereInfo *pWInfo){
if( pLoop->wsFlags & (WHERE_INDEXED|WHERE_IDX_ONLY) ){
pIdx = pLoop->u.btree.pIndex;
}else if( pLoop->wsFlags & WHERE_MULTI_OR ){
- pIdx = pLevel->u.pCovidx;
+ pIdx = pLevel->u.pCoveringIdx;
}
if( pIdx
&& !db->mallocFailed
@@ -156614,7 +165694,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3WhereEnd(WhereInfo *pWInfo){
#endif
pOp = sqlcipher_sqlite3VdbeGetOp(v, k);
pLastOp = pOp + (last - k);
- assert( pOp<pLastOp );
+ assert( pOp<=pLastOp );
do{
if( pOp->p1!=pLevel->iTabCur ){
/* no-op */
@@ -156625,6 +165705,11 @@ SQLITE_PRIVATE void sqlcipher_sqlite3WhereEnd(WhereInfo *pWInfo){
){
int x = pOp->p2;
assert( pIdx->pTable==pTab );
+#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
+ if( pOp->opcode==OP_Offset ){
+ /* Do not need to translate the column number */
+ }else
+#endif
if( !HasRowid(pTab) ){
Index *pPk = sqlcipher_sqlite3PrimaryKeyIndex(pTab);
x = pPk->aiColumn[x];
@@ -156638,9 +165723,22 @@ SQLITE_PRIVATE void sqlcipher_sqlite3WhereEnd(WhereInfo *pWInfo){
pOp->p2 = x;
pOp->p1 = pLevel->iIdxCur;
OpcodeRewriteTrace(db, k, pOp);
+ }else{
+ /* Unable to translate the table reference into an index
+ ** reference. Verify that this is harmless - that the
+ ** table being referenced really is open.
+ */
+#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
+ assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0
+ || cursorIsOpen(v,pOp->p1,k)
+ || pOp->opcode==OP_Offset
+ );
+#else
+ assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0
+ || cursorIsOpen(v,pOp->p1,k)
+ );
+#endif
}
- assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 || x>=0
- || pWInfo->eOnePass );
}else if( pOp->opcode==OP_Rowid ){
pOp->p1 = pLevel->iIdxCur;
pOp->opcode = OP_IdxRowid;
@@ -156659,18 +165757,16 @@ SQLITE_PRIVATE void sqlcipher_sqlite3WhereEnd(WhereInfo *pWInfo){
}
}
- /* Undo all Expr node modifications */
- while( pWInfo->pExprMods ){
- WhereExprMod *p = pWInfo->pExprMods;
- pWInfo->pExprMods = p->pNext;
- memcpy(p->pExpr, &p->orig, sizeof(p->orig));
- sqlcipher_sqlite3DbFree(db, p);
- }
+ /* The "break" point is here, just past the end of the outer loop.
+ ** Set it.
+ */
+ sqlcipher_sqlite3VdbeResolveLabel(v, pWInfo->iBreak);
/* Final cleanup
*/
pParse->nQueryLoop = pWInfo->savedNQueryLoop;
whereInfoFree(db, pWInfo);
+ pParse->withinRJSubrtn -= nRJ;
return;
}
@@ -157259,7 +166355,7 @@ static void noopValueFunc(sqlcipher_sqlite3_context *p){ UNUSED_PARAMETER(p); /*
/* Window functions that use all window interfaces: xStep, xFinal,
** xValue, and xInverse */
#define WINDOWFUNCALL(name,nArg,extra) { \
- nArg, (SQLITE_UTF8|SQLITE_FUNC_WINDOW|extra), 0, 0, \
+ nArg, (SQLITE_FUNC_BUILTIN|SQLITE_UTF8|SQLITE_FUNC_WINDOW|extra), 0, 0, \
name ## StepFunc, name ## FinalizeFunc, name ## ValueFunc, \
name ## InvFunc, name ## Name, {0} \
}
@@ -157267,7 +166363,7 @@ static void noopValueFunc(sqlcipher_sqlite3_context *p){ UNUSED_PARAMETER(p); /*
/* Window functions that are implemented using bytecode and thus have
** no-op routines for their methods */
#define WINDOWFUNCNOOP(name,nArg,extra) { \
- nArg, (SQLITE_UTF8|SQLITE_FUNC_WINDOW|extra), 0, 0, \
+ nArg, (SQLITE_FUNC_BUILTIN|SQLITE_UTF8|SQLITE_FUNC_WINDOW|extra), 0, 0, \
noopStepFunc, noopValueFunc, noopValueFunc, \
noopStepFunc, name ## Name, {0} \
}
@@ -157276,7 +166372,7 @@ static void noopValueFunc(sqlcipher_sqlite3_context *p){ UNUSED_PARAMETER(p); /*
** same routine for xFinalize and xValue and which never call
** xInverse. */
#define WINDOWFUNCX(name,nArg,extra) { \
- nArg, (SQLITE_UTF8|SQLITE_FUNC_WINDOW|extra), 0, 0, \
+ nArg, (SQLITE_FUNC_BUILTIN|SQLITE_UTF8|SQLITE_FUNC_WINDOW|extra), 0, 0, \
name ## StepFunc, name ## ValueFunc, name ## ValueFunc, \
noopStepFunc, name ## Name, {0} \
}
@@ -157402,7 +166498,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3WindowUpdate(
}
}
}
- pWin->pFunc = pFunc;
+ pWin->pWFunc = pFunc;
}
/*
@@ -157466,6 +166562,7 @@ static int selectWindowRewriteExprCb(Walker *pWalker, Expr *pExpr){
case TK_AGG_FUNCTION:
case TK_COLUMN: {
int iCol = -1;
+ if( pParse->db->mallocFailed ) return WRC_Abort;
if( p->pSub ){
int i;
for(i=0; i<p->pSub->nExpr; i++){
@@ -157575,14 +166672,17 @@ static ExprList *exprListAppendList(
int i;
int nInit = pList ? pList->nExpr : 0;
for(i=0; i<pAppend->nExpr; i++){
- Expr *pDup = sqlcipher_sqlite3ExprDup(pParse->db, pAppend->a[i].pExpr, 0);
+ sqlcipher_sqlite3 *db = pParse->db;
+ Expr *pDup = sqlcipher_sqlite3ExprDup(db, pAppend->a[i].pExpr, 0);
assert( pDup==0 || !ExprHasProperty(pDup, EP_MemToken) );
- if( bIntToNull && pDup ){
+ if( db->mallocFailed ){
+ sqlcipher_sqlite3ExprDelete(db, pDup);
+ break;
+ }
+ if( bIntToNull ){
int iDummy;
Expr *pSub;
- for(pSub=pDup; ExprHasProperty(pSub, EP_Skip); pSub=pSub->pLeft){
- assert( pSub );
- }
+ pSub = sqlcipher_sqlite3ExprSkipCollateAndLikely(pDup);
if( sqlcipher_sqlite3ExprIsInteger(pSub, &iDummy) ){
pSub->op = TK_NULL;
pSub->flags &= ~(EP_IntValue|EP_IsTrue|EP_IsFalse);
@@ -157590,7 +166690,7 @@ static ExprList *exprListAppendList(
}
}
pList = sqlcipher_sqlite3ExprListAppend(pParse, pList, pDup);
- if( pList ) pList->a[nInit+i].sortFlags = pAppend->a[i].sortFlags;
+ if( pList ) pList->a[nInit+i].fg.sortFlags = pAppend->a[i].fg.sortFlags;
}
}
return pList;
@@ -157613,6 +166713,15 @@ static int sqlcipher_sqlite3WindowExtraAggFuncDepth(Walker *pWalker, Expr *pExpr
return WRC_Continue;
}
+static int disallowAggregatesInOrderByCb(Walker *pWalker, Expr *pExpr){
+ if( pExpr->op==TK_AGG_FUNCTION && pExpr->pAggInfo==0 ){
+ assert( !ExprHasProperty(pExpr, EP_IntValue) );
+ sqlcipher_sqlite3ErrorMsg(pWalker->pParse,
+ "misuse of aggregate: %s()", pExpr->u.zToken);
+ }
+ return WRC_Continue;
+}
+
/*
** If the SELECT statement passed as the second argument does not invoke
** any SQL window functions, this function is a no-op. Otherwise, it
@@ -157622,7 +166731,11 @@ static int sqlcipher_sqlite3WindowExtraAggFuncDepth(Walker *pWalker, Expr *pExpr
*/
SQLITE_PRIVATE int sqlcipher_sqlite3WindowRewrite(Parse *pParse, Select *p){
int rc = SQLITE_OK;
- if( p->pWin && p->pPrior==0 && (p->selFlags & SF_WinRewrite)==0 ){
+ if( p->pWin
+ && p->pPrior==0
+ && ALWAYS((p->selFlags & SF_WinRewrite)==0)
+ && ALWAYS(!IN_RENAME_OBJECT)
+ ){
Vdbe *v = sqlcipher_sqlite3GetVdbe(pParse);
sqlcipher_sqlite3 *db = pParse->db;
Select *pSub = 0; /* The subquery */
@@ -157646,6 +166759,11 @@ SQLITE_PRIVATE int sqlcipher_sqlite3WindowRewrite(Parse *pParse, Select *p){
}
sqlcipher_sqlite3AggInfoPersistWalkerInit(&w, pParse);
sqlcipher_sqlite3WalkSelect(&w, p);
+ if( (p->selFlags & SF_Aggregate)==0 ){
+ w.xExprCallback = disallowAggregatesInOrderByCb;
+ w.xSelectCallback = 0;
+ sqlcipher_sqlite3WalkExprList(&w, p->pOrderBy);
+ }
p->pSrc = 0;
p->pWhere = 0;
@@ -157690,8 +166808,11 @@ SQLITE_PRIVATE int sqlcipher_sqlite3WindowRewrite(Parse *pParse, Select *p){
** window function - one for the accumulator, another for interim
** results. */
for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
- ExprList *pArgs = pWin->pOwner->x.pList;
- if( pWin->pFunc->funcFlags & SQLITE_FUNC_SUBTYPE ){
+ ExprList *pArgs;
+ assert( ExprUseXList(pWin->pOwner) );
+ assert( pWin->pWFunc!=0 );
+ pArgs = pWin->pOwner->x.pList;
+ if( pWin->pWFunc->funcFlags & SQLITE_FUNC_SUBTYPE ){
selectWindowRewriteEList(pParse, pMWin, pSrc, pArgs, pTab, &pSublist);
pWin->iArgCol = (pSublist ? pSublist->nExpr : 0);
pWin->bExprArgs = 1;
@@ -157727,11 +166848,14 @@ SQLITE_PRIVATE int sqlcipher_sqlite3WindowRewrite(Parse *pParse, Select *p){
("New window-function subquery in FROM clause of (%u/%p)\n",
p->selId, p));
p->pSrc = sqlcipher_sqlite3SrcListAppend(pParse, 0, 0, 0);
+ assert( pSub!=0 || p->pSrc==0 ); /* Due to db->mallocFailed test inside
+ ** of sqlcipher_sqlite3DbMallocRawNN() called from
+ ** sqlcipher_sqlite3SrcListAppend() */
if( p->pSrc ){
Table *pTab2;
p->pSrc->a[0].pSelect = pSub;
sqlcipher_sqlite3SrcListAssignCursors(pParse, p->pSrc);
- pSub->selFlags |= SF_Expanded;
+ pSub->selFlags |= SF_Expanded|SF_OrderByReqd;
pTab2 = sqlcipher_sqlite3ResultSetOfSelect(pParse, pSub, SQLITE_AFF_NONE);
pSub->selFlags |= (selFlags & SF_Aggregate);
if( pTab2==0 ){
@@ -157754,15 +166878,14 @@ SQLITE_PRIVATE int sqlcipher_sqlite3WindowRewrite(Parse *pParse, Select *p){
sqlcipher_sqlite3SelectDelete(db, pSub);
}
if( db->mallocFailed ) rc = SQLITE_NOMEM;
- sqlcipher_sqlite3DbFree(db, pTab);
- }
- if( rc ){
- if( pParse->nErr==0 ){
- assert( pParse->db->mallocFailed );
- sqlcipher_sqlite3ErrorToParser(pParse->db, SQLITE_NOMEM);
- }
+ /* Defer deleting the temporary table pTab because if an error occurred,
+ ** there could still be references to that table embedded in the
+ ** result-set or ORDER BY clause of the SELECT statement p. */
+ sqlcipher_sqlite3ParserAddCleanup(pParse, sqlcipher_sqlite3DbFree, pTab);
}
+
+ assert( rc==SQLITE_OK || pParse->nErr!=0 );
return rc;
}
@@ -157982,15 +167105,19 @@ SQLITE_PRIVATE void sqlcipher_sqlite3WindowAttach(Parse *pParse, Expr *p, Window
** SELECT, or (b) the windows already linked use a compatible window frame.
*/
SQLITE_PRIVATE void sqlcipher_sqlite3WindowLink(Select *pSel, Window *pWin){
- if( pSel!=0
- && (0==pSel->pWin || 0==sqlcipher_sqlite3WindowCompare(0, pSel->pWin, pWin, 0))
- ){
- pWin->pNextWin = pSel->pWin;
- if( pSel->pWin ){
- pSel->pWin->ppThis = &pWin->pNextWin;
+ if( pSel ){
+ if( 0==pSel->pWin || 0==sqlcipher_sqlite3WindowCompare(0, pSel->pWin, pWin, 0) ){
+ pWin->pNextWin = pSel->pWin;
+ if( pSel->pWin ){
+ pSel->pWin->ppThis = &pWin->pNextWin;
+ }
+ pSel->pWin = pWin;
+ pWin->ppThis = &pSel->pWin;
+ }else{
+ if( sqlcipher_sqlite3ExprListCompare(pWin->pPartition, pSel->pWin->pPartition,-1) ){
+ pSel->selFlags |= SF_MultiPart;
+ }
}
- pSel->pWin = pWin;
- pWin->ppThis = &pSel->pWin;
}
}
@@ -157999,7 +167126,12 @@ SQLITE_PRIVATE void sqlcipher_sqlite3WindowLink(Select *pSel, Window *pWin){
** different, or 2 if it cannot be determined if the objects are identical
** or not. Identical window objects can be processed in a single scan.
*/
-SQLITE_PRIVATE int sqlcipher_sqlite3WindowCompare(Parse *pParse, Window *p1, Window *p2, int bFilter){
+SQLITE_PRIVATE int sqlcipher_sqlite3WindowCompare(
+ const Parse *pParse,
+ const Window *p1,
+ const Window *p2,
+ int bFilter
+){
int res;
if( NEVER(p1==0) || NEVER(p2==0) ) return 1;
if( p1->eFrmType!=p2->eFrmType ) return 1;
@@ -158062,7 +167194,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3WindowCodeInit(Parse *pParse, Select *pSele
}
for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
- FuncDef *p = pWin->pFunc;
+ FuncDef *p = pWin->pWFunc;
if( (p->funcFlags & SQLITE_FUNC_MINMAX) && pWin->eStart!=TK_UNBOUNDED ){
/* The inline versions of min() and max() require a single ephemeral
** table and 3 registers. The registers are used as follows:
@@ -158071,12 +167203,15 @@ SQLITE_PRIVATE void sqlcipher_sqlite3WindowCodeInit(Parse *pParse, Select *pSele
** regApp+1: integer value used to ensure keys are unique
** regApp+2: output of MakeRecord
*/
- ExprList *pList = pWin->pOwner->x.pList;
- KeyInfo *pKeyInfo = sqlcipher_sqlite3KeyInfoFromExprList(pParse, pList, 0, 0);
+ ExprList *pList;
+ KeyInfo *pKeyInfo;
+ assert( ExprUseXList(pWin->pOwner) );
+ pList = pWin->pOwner->x.pList;
+ pKeyInfo = sqlcipher_sqlite3KeyInfoFromExprList(pParse, pList, 0, 0);
pWin->csrApp = pParse->nTab++;
pWin->regApp = pParse->nMem+1;
pParse->nMem += 3;
- if( pKeyInfo && pWin->pFunc->zName[1]=='i' ){
+ if( pKeyInfo && pWin->pWFunc->zName[1]=='i' ){
assert( pKeyInfo->aSortFlags[0]==0 );
pKeyInfo->aSortFlags[0] = KEYINFO_ORDER_DESC;
}
@@ -158143,6 +167278,7 @@ static void windowCheckValue(Parse *pParse, int reg, int eCond){
VdbeCoverageIf(v, eCond==2);
}
sqlcipher_sqlite3VdbeAddOp3(v, aOp[eCond], regZero, sqlcipher_sqlite3VdbeCurrentAddr(v)+2, reg);
+ sqlcipher_sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC);
VdbeCoverageNeverNullIf(v, eCond==0); /* NULL case captured by */
VdbeCoverageNeverNullIf(v, eCond==1); /* the OP_MustBeInt */
VdbeCoverageNeverNullIf(v, eCond==2);
@@ -158159,7 +167295,9 @@ static void windowCheckValue(Parse *pParse, int reg, int eCond){
** with the object passed as the only argument to this function.
*/
static int windowArgCount(Window *pWin){
- ExprList *pList = pWin->pOwner->x.pList;
+ const ExprList *pList;
+ assert( ExprUseXList(pWin->pOwner) );
+ pList = pWin->pOwner->x.pList;
return (pList ? pList->nExpr : 0);
}
@@ -158237,6 +167375,7 @@ struct WindowCodeArg {
int regGosub; /* Register used with OP_Gosub(addrGosub) */
int regArg; /* First in array of accumulator registers */
int eDelete; /* See above */
+ int regRowid;
WindowCsrAndReg start;
WindowCsrAndReg current;
@@ -158295,7 +167434,7 @@ static void windowAggStep(
Vdbe *v = sqlcipher_sqlite3GetVdbe(pParse);
Window *pWin;
for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
- FuncDef *pFunc = pWin->pFunc;
+ FuncDef *pFunc = pWin->pWFunc;
int regArg;
int nArg = pWin->bExprArgs ? 0 : windowArgCount(pWin);
int i;
@@ -158343,6 +167482,7 @@ static void windowAggStep(
int addrIf = 0;
if( pWin->pFilter ){
int regTmp;
+ assert( ExprUseXList(pWin->pOwner) );
assert( pWin->bExprArgs || !nArg ||nArg==pWin->pOwner->x.pList->nExpr );
assert( pWin->bExprArgs || nArg ||pWin->pOwner->x.pList==0 );
regTmp = sqlcipher_sqlite3GetTempReg(pParse);
@@ -158353,16 +167493,17 @@ static void windowAggStep(
}
if( pWin->bExprArgs ){
- int iStart = sqlcipher_sqlite3VdbeCurrentAddr(v);
- VdbeOp *pOp, *pEnd;
+ int iOp = sqlcipher_sqlite3VdbeCurrentAddr(v);
+ int iEnd;
+ assert( ExprUseXList(pWin->pOwner) );
nArg = pWin->pOwner->x.pList->nExpr;
regArg = sqlcipher_sqlite3GetTempRange(pParse, nArg);
sqlcipher_sqlite3ExprCodeExprList(pParse, pWin->pOwner->x.pList, regArg, 0, 0);
- pEnd = sqlcipher_sqlite3VdbeGetOp(v, -1);
- for(pOp=sqlcipher_sqlite3VdbeGetOp(v, iStart); pOp<=pEnd; pOp++){
- if( pOp->opcode==OP_Column && pOp->p1==pWin->iEphCsr ){
+ for(iEnd=sqlcipher_sqlite3VdbeCurrentAddr(v); iOp<iEnd; iOp++){
+ VdbeOp *pOp = sqlcipher_sqlite3VdbeGetOp(v, iOp);
+ if( pOp->opcode==OP_Column && pOp->p1==pMWin->iEphCsr ){
pOp->p1 = csr;
}
}
@@ -158370,6 +167511,7 @@ static void windowAggStep(
if( pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){
CollSeq *pColl;
assert( nArg>0 );
+ assert( ExprUseXList(pWin->pOwner) );
pColl = sqlcipher_sqlite3ExprNNCollSeq(pParse, pWin->pOwner->x.pList->a[0].pExpr);
sqlcipher_sqlite3VdbeAddOp4(v, OP_CollSeq, 0,0,0, (const char*)pColl, P4_COLLSEQ);
}
@@ -158406,7 +167548,7 @@ static void windowAggFinal(WindowCodeArg *p, int bFin){
for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
if( pMWin->regStartRowid==0
- && (pWin->pFunc->funcFlags & SQLITE_FUNC_MINMAX)
+ && (pWin->pWFunc->funcFlags & SQLITE_FUNC_MINMAX)
&& (pWin->eStart!=TK_UNBOUNDED)
){
sqlcipher_sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regResult);
@@ -158420,12 +167562,12 @@ static void windowAggFinal(WindowCodeArg *p, int bFin){
int nArg = windowArgCount(pWin);
if( bFin ){
sqlcipher_sqlite3VdbeAddOp2(v, OP_AggFinal, pWin->regAccum, nArg);
- sqlcipher_sqlite3VdbeAppendP4(v, pWin->pFunc, P4_FUNCDEF);
+ sqlcipher_sqlite3VdbeAppendP4(v, pWin->pWFunc, P4_FUNCDEF);
sqlcipher_sqlite3VdbeAddOp2(v, OP_Copy, pWin->regAccum, pWin->regResult);
sqlcipher_sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regAccum);
}else{
sqlcipher_sqlite3VdbeAddOp3(v, OP_AggValue,pWin->regAccum,nArg,pWin->regResult);
- sqlcipher_sqlite3VdbeAppendP4(v, pWin->pFunc, P4_FUNCDEF);
+ sqlcipher_sqlite3VdbeAppendP4(v, pWin->pWFunc, P4_FUNCDEF);
}
}
}
@@ -158554,7 +167696,8 @@ static void windowReturnOneRow(WindowCodeArg *p){
Window *pWin;
for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
- FuncDef *pFunc = pWin->pFunc;
+ FuncDef *pFunc = pWin->pWFunc;
+ assert( ExprUseXList(pWin->pOwner) );
if( pFunc->zName==nth_valueName
|| pFunc->zName==first_valueName
){
@@ -158625,7 +167768,7 @@ static int windowInitAccum(Parse *pParse, Window *pMWin){
int nArg = 0;
Window *pWin;
for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
- FuncDef *pFunc = pWin->pFunc;
+ FuncDef *pFunc = pWin->pWFunc;
assert( pWin->regAccum );
sqlcipher_sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regAccum);
nArg = MAX(nArg, windowArgCount(pWin));
@@ -158655,7 +167798,7 @@ static int windowCacheFrame(Window *pMWin){
Window *pWin;
if( pMWin->regStartRowid ) return 1;
for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
- FuncDef *pFunc = pWin->pFunc;
+ FuncDef *pFunc = pWin->pWFunc;
if( (pFunc->zName==nth_valueName)
|| (pFunc->zName==first_valueName)
|| (pFunc->zName==leadName)
@@ -158720,7 +167863,7 @@ static void windowIfNewPeer(
** if( csr1.peerVal - regVal <= csr2.peerVal ) goto lbl;
**
** A special type of arithmetic is used such that if csr1.peerVal is not
-** a numeric type (real or integer), then the result of the addition addition
+** a numeric type (real or integer), then the result of the addition
** or subtraction is a a copy of csr1.peerVal.
*/
static void windowCodeRangeTest(
@@ -158739,10 +167882,16 @@ static void windowCodeRangeTest(
int regString = ++pParse->nMem; /* Reg. for constant value '' */
int arith = OP_Add; /* OP_Add or OP_Subtract */
int addrGe; /* Jump destination */
+ int addrDone = sqlcipher_sqlite3VdbeMakeLabel(pParse); /* Address past OP_Ge */
+ CollSeq *pColl;
+
+ /* Read the peer-value from each cursor into a register */
+ windowReadPeerValues(p, csr1, reg1);
+ windowReadPeerValues(p, csr2, reg2);
assert( op==OP_Ge || op==OP_Gt || op==OP_Le );
assert( pOrderBy && pOrderBy->nExpr==1 );
- if( pOrderBy->a[0].sortFlags & KEYINFO_ORDER_DESC ){
+ if( pOrderBy->a[0].fg.sortFlags & KEYINFO_ORDER_DESC ){
switch( op ){
case OP_Ge: op = OP_Le; break;
case OP_Gt: op = OP_Lt; break;
@@ -158751,34 +167900,11 @@ static void windowCodeRangeTest(
arith = OP_Subtract;
}
- /* Read the peer-value from each cursor into a register */
- windowReadPeerValues(p, csr1, reg1);
- windowReadPeerValues(p, csr2, reg2);
-
VdbeModuleComment((v, "CodeRangeTest: if( R%d %s R%d %s R%d ) goto lbl",
reg1, (arith==OP_Add ? "+" : "-"), regVal,
((op==OP_Ge) ? ">=" : (op==OP_Le) ? "<=" : (op==OP_Gt) ? ">" : "<"), reg2
));
- /* Register reg1 currently contains csr1.peerVal (the peer-value from csr1).
- ** This block adds (or subtracts for DESC) the numeric value in regVal
- ** from it. Or, if reg1 is not numeric (it is a NULL, a text value or a blob),
- ** then leave reg1 as it is. In pseudo-code, this is implemented as:
- **
- ** if( reg1>='' ) goto addrGe;
- ** reg1 = reg1 +/- regVal
- ** addrGe:
- **
- ** Since all strings and blobs are greater-than-or-equal-to an empty string,
- ** the add/subtract is skipped for these, as required. If reg1 is a NULL,
- ** then the arithmetic is performed, but since adding or subtracting from
- ** NULL is always NULL anyway, this case is handled as required too. */
- sqlcipher_sqlite3VdbeAddOp4(v, OP_String8, 0, regString, 0, "", P4_STATIC);
- addrGe = sqlcipher_sqlite3VdbeAddOp3(v, OP_Ge, regString, 0, reg1);
- VdbeCoverage(v);
- sqlcipher_sqlite3VdbeAddOp3(v, arith, regVal, reg1, reg1);
- sqlcipher_sqlite3VdbeJumpHere(v, addrGe);
-
/* If the BIGNULL flag is set for the ORDER BY, then it is required to
** consider NULL values to be larger than all other values, instead of
** the usual smaller. The VDBE opcodes OP_Ge and so on do not handle this
@@ -158798,7 +167924,7 @@ static void windowCodeRangeTest(
** Additionally, if either reg1 or reg2 are NULL but the jump to lbl is
** not taken, control jumps over the comparison operator coded below this
** block. */
- if( pOrderBy->a[0].sortFlags & KEYINFO_ORDER_BIGNULL ){
+ if( pOrderBy->a[0].fg.sortFlags & KEYINFO_ORDER_BIGNULL ){
/* This block runs if reg1 contains a NULL. */
int addr = sqlcipher_sqlite3VdbeAddOp1(v, OP_NotNull, reg1); VdbeCoverage(v);
switch( op ){
@@ -158815,21 +167941,46 @@ static void windowCodeRangeTest(
break;
default: assert( op==OP_Lt ); /* no-op */ break;
}
- sqlcipher_sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlcipher_sqlite3VdbeCurrentAddr(v)+3);
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_Goto, 0, addrDone);
/* This block runs if reg1 is not NULL, but reg2 is. */
sqlcipher_sqlite3VdbeJumpHere(v, addr);
sqlcipher_sqlite3VdbeAddOp2(v, OP_IsNull, reg2, lbl); VdbeCoverage(v);
if( op==OP_Gt || op==OP_Ge ){
- sqlcipher_sqlite3VdbeChangeP2(v, -1, sqlcipher_sqlite3VdbeCurrentAddr(v)+1);
+ sqlcipher_sqlite3VdbeChangeP2(v, -1, addrDone);
}
}
+ /* Register reg1 currently contains csr1.peerVal (the peer-value from csr1).
+ ** This block adds (or subtracts for DESC) the numeric value in regVal
+ ** from it. Or, if reg1 is not numeric (it is a NULL, a text value or a blob),
+ ** then leave reg1 as it is. In pseudo-code, this is implemented as:
+ **
+ ** if( reg1>='' ) goto addrGe;
+ ** reg1 = reg1 +/- regVal
+ ** addrGe:
+ **
+ ** Since all strings and blobs are greater-than-or-equal-to an empty string,
+ ** the add/subtract is skipped for these, as required. If reg1 is a NULL,
+ ** then the arithmetic is performed, but since adding or subtracting from
+ ** NULL is always NULL anyway, this case is handled as required too. */
+ sqlcipher_sqlite3VdbeAddOp4(v, OP_String8, 0, regString, 0, "", P4_STATIC);
+ addrGe = sqlcipher_sqlite3VdbeAddOp3(v, OP_Ge, regString, 0, reg1);
+ VdbeCoverage(v);
+ if( (op==OP_Ge && arith==OP_Add) || (op==OP_Le && arith==OP_Subtract) ){
+ sqlcipher_sqlite3VdbeAddOp3(v, op, reg2, lbl, reg1); VdbeCoverage(v);
+ }
+ sqlcipher_sqlite3VdbeAddOp3(v, arith, regVal, reg1, reg1);
+ sqlcipher_sqlite3VdbeJumpHere(v, addrGe);
+
/* Compare registers reg2 and reg1, taking the jump if required. Note that
** control skips over this test if the BIGNULL flag is set and either
** reg1 or reg2 contain a NULL value. */
sqlcipher_sqlite3VdbeAddOp3(v, op, reg2, lbl, reg1); VdbeCoverage(v);
+ pColl = sqlcipher_sqlite3ExprNNCollSeq(pParse, pOrderBy->a[0].pExpr);
+ sqlcipher_sqlite3VdbeAppendP4(v, (void*)pColl, P4_COLLSEQ);
sqlcipher_sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
+ sqlcipher_sqlite3VdbeResolveLabel(v, addrDone);
assert( op==OP_Ge || op==OP_Gt || op==OP_Lt || op==OP_Le );
testcase(op==OP_Ge); VdbeCoverageIf(v, op==OP_Ge);
@@ -158905,16 +168056,24 @@ static int windowCodeOp(
/* If this is a (RANGE BETWEEN a FOLLOWING AND b FOLLOWING) or
** (RANGE BETWEEN b PRECEDING AND a PRECEDING) frame, ensure the
** start cursor does not advance past the end cursor within the
- ** temporary table. It otherwise might, if (a>b). */
+ ** temporary table. It otherwise might, if (a>b). Also ensure that,
+ ** if the input cursor is still finding new rows, that the end
+ ** cursor does not go past it to EOF. */
if( pMWin->eStart==pMWin->eEnd && regCountdown
- && pMWin->eFrmType==TK_RANGE && op==WINDOW_AGGINVERSE
+ && pMWin->eFrmType==TK_RANGE
){
int regRowid1 = sqlcipher_sqlite3GetTempReg(pParse);
int regRowid2 = sqlcipher_sqlite3GetTempReg(pParse);
- sqlcipher_sqlite3VdbeAddOp2(v, OP_Rowid, p->start.csr, regRowid1);
- sqlcipher_sqlite3VdbeAddOp2(v, OP_Rowid, p->end.csr, regRowid2);
- sqlcipher_sqlite3VdbeAddOp3(v, OP_Ge, regRowid2, lblDone, regRowid1);
- VdbeCoverage(v);
+ if( op==WINDOW_AGGINVERSE ){
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_Rowid, p->start.csr, regRowid1);
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_Rowid, p->end.csr, regRowid2);
+ sqlcipher_sqlite3VdbeAddOp3(v, OP_Ge, regRowid2, lblDone, regRowid1);
+ VdbeCoverage(v);
+ }else if( p->regRowid ){
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_Rowid, p->end.csr, regRowid1);
+ sqlcipher_sqlite3VdbeAddOp3(v, OP_Ge, p->regRowid, lblDone, regRowid1);
+ VdbeCoverageNeverNull(v);
+ }
sqlcipher_sqlite3ReleaseTempReg(pParse, regRowid1);
sqlcipher_sqlite3ReleaseTempReg(pParse, regRowid2);
assert( pMWin->eStart==TK_PRECEDING || pMWin->eStart==TK_FOLLOWING );
@@ -158997,7 +168156,7 @@ SQLITE_PRIVATE Window *sqlcipher_sqlite3WindowDup(sqlcipher_sqlite3 *db, Expr *p
pNew->zName = sqlcipher_sqlite3DbStrDup(db, p->zName);
pNew->zBase = sqlcipher_sqlite3DbStrDup(db, p->zBase);
pNew->pFilter = sqlcipher_sqlite3ExprDup(db, p->pFilter, 0);
- pNew->pFunc = p->pFunc;
+ pNew->pWFunc = p->pWFunc;
pNew->pPartition = sqlcipher_sqlite3ExprListDup(db, p->pPartition, 0);
pNew->pOrderBy = sqlcipher_sqlite3ExprListDup(db, p->pOrderBy, 0);
pNew->eFrmType = p->eFrmType;
@@ -159411,7 +168570,6 @@ SQLITE_PRIVATE void sqlcipher_sqlite3WindowCodeStep(
int addrEmpty; /* Address of OP_Rewind in flush: */
int regNew; /* Array of registers holding new input row */
int regRecord; /* regNew array in record form */
- int regRowid; /* Rowid for regRecord in eph table */
int regNewPeer = 0; /* Peer values for new row (part of regNew) */
int regPeer = 0; /* Peer values for current row */
int regFlushPart = 0; /* Register for "Gosub flush_partition" */
@@ -159483,7 +168641,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3WindowCodeStep(
regNew = pParse->nMem+1;
pParse->nMem += nInput;
regRecord = ++pParse->nMem;
- regRowid = ++pParse->nMem;
+ s.regRowid = ++pParse->nMem;
/* If the window frame contains an "<expr> PRECEDING" or "<expr> FOLLOWING"
** clause, allocate registers to store the results of evaluating each
@@ -159539,9 +168697,9 @@ SQLITE_PRIVATE void sqlcipher_sqlite3WindowCodeStep(
}
/* Insert the new row into the ephemeral table */
- sqlcipher_sqlite3VdbeAddOp2(v, OP_NewRowid, csrWrite, regRowid);
- sqlcipher_sqlite3VdbeAddOp3(v, OP_Insert, csrWrite, regRecord, regRowid);
- addrNe = sqlcipher_sqlite3VdbeAddOp3(v, OP_Ne, pMWin->regOne, 0, regRowid);
+ sqlcipher_sqlite3VdbeAddOp2(v, OP_NewRowid, csrWrite, s.regRowid);
+ sqlcipher_sqlite3VdbeAddOp3(v, OP_Insert, csrWrite, regRecord, s.regRowid);
+ addrNe = sqlcipher_sqlite3VdbeAddOp3(v, OP_Ne, pMWin->regOne, 0, s.regRowid);
VdbeCoverageNeverNull(v);
/* This block is run for the first row of each partition */
@@ -159659,6 +168817,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3WindowCodeStep(
sqlcipher_sqlite3VdbeJumpHere(v, addrGosubFlush);
}
+ s.regRowid = 0;
addrEmpty = sqlcipher_sqlite3VdbeAddOp1(v, OP_Rewind, csrWrite);
VdbeCoverage(v);
if( pMWin->eEnd==TK_PRECEDING ){
@@ -159835,11 +168994,21 @@ static void updateDeleteLimitError(
static void parserDoubleLinkSelect(Parse *pParse, Select *p){
assert( p!=0 );
if( p->pPrior ){
- Select *pNext = 0, *pLoop;
- int mxSelect, cnt = 0;
- for(pLoop=p; pLoop; pNext=pLoop, pLoop=pLoop->pPrior, cnt++){
+ Select *pNext = 0, *pLoop = p;
+ int mxSelect, cnt = 1;
+ while(1){
pLoop->pNext = pNext;
pLoop->selFlags |= SF_Compound;
+ pNext = pLoop;
+ pLoop = pLoop->pPrior;
+ if( pLoop==0 ) break;
+ cnt++;
+ if( pLoop->pOrderBy || pLoop->pLimit ){
+ sqlcipher_sqlite3ErrorMsg(pParse,"%s clause should come after %s not before",
+ pLoop->pOrderBy!=0 ? "ORDER BY" : "LIMIT",
+ sqlcipher_sqlite3SelectOpName(pNext->op));
+ break;
+ }
}
if( (p->selFlags & SF_MultiValue)==0 &&
(mxSelect = pParse->db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT])>0 &&
@@ -159850,11 +169019,21 @@ static void updateDeleteLimitError(
}
}
-
- /* Construct a new Expr object from a single identifier. Use the
- ** new Expr to populate pOut. Set the span of pOut to be the identifier
- ** that created the expression.
+ /* Attach a With object describing the WITH clause to a Select
+ ** object describing the query for which the WITH clause is a prefix.
*/
+ static Select *attachWithToSelect(Parse *pParse, Select *pSelect, With *pWith){
+ if( pSelect ){
+ pSelect->pWith = pWith;
+ parserDoubleLinkSelect(pParse, pSelect);
+ }else{
+ sqlcipher_sqlite3WithDelete(pParse->db, pWith);
+ }
+ return pSelect;
+ }
+
+
+ /* Construct a new Expr object from a single token */
static Expr *tokenExpr(Parse *pParse, int op, Token t){
Expr *p = sqlcipher_sqlite3DbMallocRawNN(pParse->db, sizeof(Expr)+t.n+1);
if( p ){
@@ -159863,17 +169042,18 @@ static void updateDeleteLimitError(
p->affExpr = 0;
p->flags = EP_Leaf;
ExprClearVVAProperties(p);
- p->iAgg = -1;
+ /* p->iAgg = -1; // Not required */
p->pLeft = p->pRight = 0;
- p->x.pList = 0;
p->pAggInfo = 0;
- p->y.pTab = 0;
+ memset(&p->x, 0, sizeof(p->x));
+ memset(&p->y, 0, sizeof(p->y));
p->op2 = 0;
p->iTable = 0;
p->iColumn = 0;
p->u.zToken = (char*)&p[1];
memcpy(p->u.zToken, t.z, t.n);
p->u.zToken[t.n] = 0;
+ p->w.iOfst = (int)(t.z - pParse->zTail);
if( sqlcipher_sqlite3Isquote(p->u.zToken[0]) ){
sqlcipher_sqlite3DequoteExpr(p);
}
@@ -159953,8 +169133,8 @@ static void updateDeleteLimitError(
#define TK_LP 22
#define TK_RP 23
#define TK_AS 24
-#define TK_WITHOUT 25
-#define TK_COMMA 26
+#define TK_COMMA 25
+#define TK_WITHOUT 26
#define TK_ABORT 27
#define TK_ACTION 28
#define TK_AFTER 29
@@ -160025,90 +169205,94 @@ static void updateDeleteLimitError(
#define TK_TIES 94
#define TK_GENERATED 95
#define TK_ALWAYS 96
-#define TK_REINDEX 97
-#define TK_RENAME 98
-#define TK_CTIME_KW 99
-#define TK_ANY 100
-#define TK_BITAND 101
-#define TK_BITOR 102
-#define TK_LSHIFT 103
-#define TK_RSHIFT 104
-#define TK_PLUS 105
-#define TK_MINUS 106
-#define TK_STAR 107
-#define TK_SLASH 108
-#define TK_REM 109
-#define TK_CONCAT 110
-#define TK_COLLATE 111
-#define TK_BITNOT 112
-#define TK_ON 113
-#define TK_INDEXED 114
-#define TK_STRING 115
-#define TK_JOIN_KW 116
-#define TK_CONSTRAINT 117
-#define TK_DEFAULT 118
-#define TK_NULL 119
-#define TK_PRIMARY 120
-#define TK_UNIQUE 121
-#define TK_CHECK 122
-#define TK_REFERENCES 123
-#define TK_AUTOINCR 124
-#define TK_INSERT 125
-#define TK_DELETE 126
-#define TK_UPDATE 127
-#define TK_SET 128
-#define TK_DEFERRABLE 129
-#define TK_FOREIGN 130
-#define TK_DROP 131
-#define TK_UNION 132
-#define TK_ALL 133
-#define TK_EXCEPT 134
-#define TK_INTERSECT 135
-#define TK_SELECT 136
-#define TK_VALUES 137
-#define TK_DISTINCT 138
-#define TK_DOT 139
-#define TK_FROM 140
-#define TK_JOIN 141
-#define TK_USING 142
-#define TK_ORDER 143
-#define TK_GROUP 144
-#define TK_HAVING 145
-#define TK_LIMIT 146
-#define TK_WHERE 147
-#define TK_INTO 148
-#define TK_NOTHING 149
-#define TK_FLOAT 150
-#define TK_BLOB 151
-#define TK_INTEGER 152
-#define TK_VARIABLE 153
-#define TK_CASE 154
-#define TK_WHEN 155
-#define TK_THEN 156
-#define TK_ELSE 157
-#define TK_INDEX 158
-#define TK_ALTER 159
-#define TK_ADD 160
-#define TK_WINDOW 161
-#define TK_OVER 162
-#define TK_FILTER 163
-#define TK_COLUMN 164
-#define TK_AGG_FUNCTION 165
-#define TK_AGG_COLUMN 166
-#define TK_TRUEFALSE 167
-#define TK_ISNOT 168
-#define TK_FUNCTION 169
-#define TK_UMINUS 170
-#define TK_UPLUS 171
-#define TK_TRUTH 172
-#define TK_REGISTER 173
-#define TK_VECTOR 174
-#define TK_SELECT_COLUMN 175
-#define TK_IF_NULL_ROW 176
-#define TK_ASTERISK 177
-#define TK_SPAN 178
-#define TK_SPACE 179
-#define TK_ILLEGAL 180
+#define TK_MATERIALIZED 97
+#define TK_REINDEX 98
+#define TK_RENAME 99
+#define TK_CTIME_KW 100
+#define TK_ANY 101
+#define TK_BITAND 102
+#define TK_BITOR 103
+#define TK_LSHIFT 104
+#define TK_RSHIFT 105
+#define TK_PLUS 106
+#define TK_MINUS 107
+#define TK_STAR 108
+#define TK_SLASH 109
+#define TK_REM 110
+#define TK_CONCAT 111
+#define TK_PTR 112
+#define TK_COLLATE 113
+#define TK_BITNOT 114
+#define TK_ON 115
+#define TK_INDEXED 116
+#define TK_STRING 117
+#define TK_JOIN_KW 118
+#define TK_CONSTRAINT 119
+#define TK_DEFAULT 120
+#define TK_NULL 121
+#define TK_PRIMARY 122
+#define TK_UNIQUE 123
+#define TK_CHECK 124
+#define TK_REFERENCES 125
+#define TK_AUTOINCR 126
+#define TK_INSERT 127
+#define TK_DELETE 128
+#define TK_UPDATE 129
+#define TK_SET 130
+#define TK_DEFERRABLE 131
+#define TK_FOREIGN 132
+#define TK_DROP 133
+#define TK_UNION 134
+#define TK_ALL 135
+#define TK_EXCEPT 136
+#define TK_INTERSECT 137
+#define TK_SELECT 138
+#define TK_VALUES 139
+#define TK_DISTINCT 140
+#define TK_DOT 141
+#define TK_FROM 142
+#define TK_JOIN 143
+#define TK_USING 144
+#define TK_ORDER 145
+#define TK_GROUP 146
+#define TK_HAVING 147
+#define TK_LIMIT 148
+#define TK_WHERE 149
+#define TK_RETURNING 150
+#define TK_INTO 151
+#define TK_NOTHING 152
+#define TK_FLOAT 153
+#define TK_BLOB 154
+#define TK_INTEGER 155
+#define TK_VARIABLE 156
+#define TK_CASE 157
+#define TK_WHEN 158
+#define TK_THEN 159
+#define TK_ELSE 160
+#define TK_INDEX 161
+#define TK_ALTER 162
+#define TK_ADD 163
+#define TK_WINDOW 164
+#define TK_OVER 165
+#define TK_FILTER 166
+#define TK_COLUMN 167
+#define TK_AGG_FUNCTION 168
+#define TK_AGG_COLUMN 169
+#define TK_TRUEFALSE 170
+#define TK_ISNOT 171
+#define TK_FUNCTION 172
+#define TK_UMINUS 173
+#define TK_UPLUS 174
+#define TK_TRUTH 175
+#define TK_REGISTER 176
+#define TK_VECTOR 177
+#define TK_SELECT_COLUMN 178
+#define TK_IF_NULL_ROW 179
+#define TK_ASTERISK 180
+#define TK_SPAN 181
+#define TK_ERROR 182
+#define TK_SPACE 183
+#define TK_ILLEGAL 184
#endif
/**************** End token definitions ***************************************/
@@ -160168,28 +169352,31 @@ static void updateDeleteLimitError(
#endif
/************* Begin control #defines *****************************************/
#define YYCODETYPE unsigned short int
-#define YYNOCODE 310
+#define YYNOCODE 319
#define YYACTIONTYPE unsigned short int
-#define YYWILDCARD 100
+#define YYWILDCARD 101
#define sqlcipher_sqlite3ParserTOKENTYPE Token
typedef union {
int yyinit;
sqlcipher_sqlite3ParserTOKENTYPE yy0;
- SrcList* yy47;
- u8 yy58;
- struct FrameBound yy77;
- With* yy131;
- int yy192;
- Expr* yy202;
- struct {int value; int mask;} yy207;
- struct TrigEvent yy230;
- ExprList* yy242;
- Window* yy303;
- Upsert* yy318;
- const char* yy436;
- TriggerStep* yy447;
- Select* yy539;
- IdList* yy600;
+ TriggerStep* yy33;
+ Window* yy41;
+ Select* yy47;
+ SrcList* yy131;
+ struct TrigEvent yy180;
+ struct {int value; int mask;} yy231;
+ IdList* yy254;
+ u32 yy285;
+ ExprList* yy322;
+ Cte* yy385;
+ int yy394;
+ Upsert* yy444;
+ u8 yy516;
+ With* yy521;
+ const char* yy522;
+ Expr* yy528;
+ OnOrUsing yy561;
+ struct FrameBound yy595;
} YYMINORTYPE;
#ifndef YYSTACKDEPTH
#define YYSTACKDEPTH 100
@@ -160205,18 +169392,18 @@ typedef union {
#define sqlcipher_sqlite3ParserCTX_FETCH Parse *pParse=yypParser->pParse;
#define sqlcipher_sqlite3ParserCTX_STORE yypParser->pParse=pParse;
#define YYFALLBACK 1
-#define YYNSTATE 557
-#define YYNRULE 385
-#define YYNRULE_WITH_ACTION 325
-#define YYNTOKEN 181
-#define YY_MAX_SHIFT 556
-#define YY_MIN_SHIFTREDUCE 807
-#define YY_MAX_SHIFTREDUCE 1191
-#define YY_ERROR_ACTION 1192
-#define YY_ACCEPT_ACTION 1193
-#define YY_NO_ACTION 1194
-#define YY_MIN_REDUCE 1195
-#define YY_MAX_REDUCE 1579
+#define YYNSTATE 580
+#define YYNRULE 405
+#define YYNRULE_WITH_ACTION 342
+#define YYNTOKEN 185
+#define YY_MAX_SHIFT 579
+#define YY_MIN_SHIFTREDUCE 839
+#define YY_MAX_SHIFTREDUCE 1243
+#define YY_ERROR_ACTION 1244
+#define YY_ACCEPT_ACTION 1245
+#define YY_NO_ACTION 1246
+#define YY_MIN_REDUCE 1247
+#define YY_MAX_REDUCE 1651
/************* End control #defines *******************************************/
#define YY_NLOOKAHEAD ((int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0])))
@@ -160283,588 +169470,620 @@ typedef union {
** yy_default[] Default action for each state.
**
*********** Begin parsing tables **********************************************/
-#define YY_ACTTAB_COUNT (1974)
+#define YY_ACTTAB_COUNT (2101)
static const YYACTIONTYPE yy_action[] = {
- /* 0 */ 550, 1226, 550, 455, 1264, 550, 1243, 550, 114, 111,
- /* 10 */ 211, 550, 1541, 550, 1264, 527, 114, 111, 211, 396,
- /* 20 */ 1236, 348, 42, 42, 42, 42, 1229, 42, 42, 71,
- /* 30 */ 71, 941, 1228, 71, 71, 71, 71, 1466, 1497, 942,
- /* 40 */ 824, 457, 6, 121, 122, 112, 1169, 1169, 1010, 1013,
- /* 50 */ 1003, 1003, 119, 119, 120, 120, 120, 120, 1547, 396,
- /* 60 */ 1362, 1521, 556, 2, 1197, 194, 532, 440, 143, 291,
- /* 70 */ 532, 136, 532, 375, 261, 508, 272, 389, 1277, 531,
- /* 80 */ 507, 497, 164, 121, 122, 112, 1169, 1169, 1010, 1013,
- /* 90 */ 1003, 1003, 119, 119, 120, 120, 120, 120, 1362, 446,
- /* 100 */ 1518, 118, 118, 118, 118, 117, 117, 116, 116, 116,
- /* 110 */ 115, 428, 266, 266, 266, 266, 1502, 362, 1504, 439,
- /* 120 */ 361, 1502, 521, 528, 1489, 547, 1118, 547, 1118, 396,
- /* 130 */ 409, 241, 208, 114, 111, 211, 98, 290, 541, 221,
- /* 140 */ 1033, 118, 118, 118, 118, 117, 117, 116, 116, 116,
- /* 150 */ 115, 428, 1146, 121, 122, 112, 1169, 1169, 1010, 1013,
- /* 160 */ 1003, 1003, 119, 119, 120, 120, 120, 120, 410, 432,
- /* 170 */ 117, 117, 116, 116, 116, 115, 428, 1422, 472, 123,
- /* 180 */ 118, 118, 118, 118, 117, 117, 116, 116, 116, 115,
- /* 190 */ 428, 116, 116, 116, 115, 428, 544, 544, 544, 396,
- /* 200 */ 509, 120, 120, 120, 120, 113, 1055, 1146, 1147, 1148,
- /* 210 */ 1055, 118, 118, 118, 118, 117, 117, 116, 116, 116,
- /* 220 */ 115, 428, 1465, 121, 122, 112, 1169, 1169, 1010, 1013,
- /* 230 */ 1003, 1003, 119, 119, 120, 120, 120, 120, 396, 448,
- /* 240 */ 320, 83, 467, 81, 363, 386, 1146, 80, 118, 118,
- /* 250 */ 118, 118, 117, 117, 116, 116, 116, 115, 428, 179,
- /* 260 */ 438, 428, 121, 122, 112, 1169, 1169, 1010, 1013, 1003,
- /* 270 */ 1003, 119, 119, 120, 120, 120, 120, 438, 437, 266,
- /* 280 */ 266, 118, 118, 118, 118, 117, 117, 116, 116, 116,
- /* 290 */ 115, 428, 547, 1113, 907, 510, 1146, 114, 111, 211,
- /* 300 */ 1435, 1146, 1147, 1148, 206, 495, 1113, 396, 453, 1113,
- /* 310 */ 549, 334, 120, 120, 120, 120, 298, 1435, 1437, 17,
- /* 320 */ 118, 118, 118, 118, 117, 117, 116, 116, 116, 115,
- /* 330 */ 428, 121, 122, 112, 1169, 1169, 1010, 1013, 1003, 1003,
- /* 340 */ 119, 119, 120, 120, 120, 120, 396, 1362, 438, 1146,
- /* 350 */ 486, 1146, 1147, 1148, 1000, 1000, 1011, 1014, 449, 118,
- /* 360 */ 118, 118, 118, 117, 117, 116, 116, 116, 115, 428,
- /* 370 */ 121, 122, 112, 1169, 1169, 1010, 1013, 1003, 1003, 119,
- /* 380 */ 119, 120, 120, 120, 120, 1058, 1058, 469, 1435, 118,
- /* 390 */ 118, 118, 118, 117, 117, 116, 116, 116, 115, 428,
- /* 400 */ 1146, 455, 550, 1430, 1146, 1147, 1148, 233, 970, 1146,
- /* 410 */ 485, 482, 481, 171, 364, 396, 164, 411, 418, 846,
- /* 420 */ 480, 164, 185, 338, 71, 71, 1247, 1004, 118, 118,
- /* 430 */ 118, 118, 117, 117, 116, 116, 116, 115, 428, 121,
- /* 440 */ 122, 112, 1169, 1169, 1010, 1013, 1003, 1003, 119, 119,
- /* 450 */ 120, 120, 120, 120, 396, 1146, 1147, 1148, 839, 12,
- /* 460 */ 318, 513, 163, 360, 1146, 1147, 1148, 114, 111, 211,
- /* 470 */ 512, 290, 541, 550, 276, 180, 290, 541, 121, 122,
- /* 480 */ 112, 1169, 1169, 1010, 1013, 1003, 1003, 119, 119, 120,
- /* 490 */ 120, 120, 120, 349, 488, 71, 71, 118, 118, 118,
- /* 500 */ 118, 117, 117, 116, 116, 116, 115, 428, 1146, 209,
- /* 510 */ 415, 527, 1146, 1113, 1575, 382, 252, 269, 346, 491,
- /* 520 */ 341, 490, 238, 396, 517, 368, 1113, 1131, 337, 1113,
- /* 530 */ 191, 413, 286, 32, 461, 447, 118, 118, 118, 118,
- /* 540 */ 117, 117, 116, 116, 116, 115, 428, 121, 122, 112,
- /* 550 */ 1169, 1169, 1010, 1013, 1003, 1003, 119, 119, 120, 120,
- /* 560 */ 120, 120, 396, 1146, 1147, 1148, 991, 1146, 1147, 1148,
- /* 570 */ 1146, 233, 496, 1496, 485, 482, 481, 6, 163, 550,
- /* 580 */ 516, 550, 115, 428, 480, 5, 121, 122, 112, 1169,
- /* 590 */ 1169, 1010, 1013, 1003, 1003, 119, 119, 120, 120, 120,
- /* 600 */ 120, 13, 13, 13, 13, 118, 118, 118, 118, 117,
- /* 610 */ 117, 116, 116, 116, 115, 428, 407, 506, 412, 550,
- /* 620 */ 1490, 548, 1146, 896, 896, 1146, 1147, 1148, 1477, 1146,
- /* 630 */ 275, 396, 812, 813, 814, 975, 426, 426, 426, 16,
- /* 640 */ 16, 55, 55, 1246, 118, 118, 118, 118, 117, 117,
- /* 650 */ 116, 116, 116, 115, 428, 121, 122, 112, 1169, 1169,
- /* 660 */ 1010, 1013, 1003, 1003, 119, 119, 120, 120, 120, 120,
- /* 670 */ 396, 1193, 1, 1, 556, 2, 1197, 1146, 1147, 1148,
- /* 680 */ 194, 291, 902, 136, 1146, 1147, 1148, 901, 525, 1496,
- /* 690 */ 1277, 3, 384, 6, 121, 122, 112, 1169, 1169, 1010,
- /* 700 */ 1013, 1003, 1003, 119, 119, 120, 120, 120, 120, 862,
- /* 710 */ 550, 928, 550, 118, 118, 118, 118, 117, 117, 116,
- /* 720 */ 116, 116, 115, 428, 266, 266, 1096, 1573, 1146, 555,
- /* 730 */ 1573, 1197, 13, 13, 13, 13, 291, 547, 136, 396,
- /* 740 */ 489, 425, 424, 970, 348, 1277, 472, 414, 863, 279,
- /* 750 */ 140, 221, 118, 118, 118, 118, 117, 117, 116, 116,
- /* 760 */ 116, 115, 428, 121, 122, 112, 1169, 1169, 1010, 1013,
- /* 770 */ 1003, 1003, 119, 119, 120, 120, 120, 120, 550, 266,
- /* 780 */ 266, 432, 396, 1146, 1147, 1148, 1176, 834, 1176, 472,
- /* 790 */ 435, 145, 547, 1150, 405, 318, 443, 304, 842, 1494,
- /* 800 */ 71, 71, 416, 6, 1094, 477, 221, 100, 112, 1169,
- /* 810 */ 1169, 1010, 1013, 1003, 1003, 119, 119, 120, 120, 120,
- /* 820 */ 120, 118, 118, 118, 118, 117, 117, 116, 116, 116,
- /* 830 */ 115, 428, 237, 1429, 550, 455, 432, 287, 990, 550,
- /* 840 */ 236, 235, 234, 834, 97, 533, 433, 1269, 1269, 1150,
- /* 850 */ 498, 311, 434, 842, 981, 550, 71, 71, 980, 1245,
- /* 860 */ 550, 51, 51, 300, 118, 118, 118, 118, 117, 117,
- /* 870 */ 116, 116, 116, 115, 428, 194, 103, 70, 70, 266,
- /* 880 */ 266, 550, 71, 71, 266, 266, 30, 395, 348, 980,
- /* 890 */ 980, 982, 547, 532, 1113, 332, 396, 547, 499, 401,
- /* 900 */ 1474, 195, 534, 13, 13, 1362, 240, 1113, 277, 280,
- /* 910 */ 1113, 280, 308, 461, 310, 337, 396, 31, 188, 423,
- /* 920 */ 121, 122, 112, 1169, 1169, 1010, 1013, 1003, 1003, 119,
- /* 930 */ 119, 120, 120, 120, 120, 142, 396, 369, 461, 990,
- /* 940 */ 121, 122, 112, 1169, 1169, 1010, 1013, 1003, 1003, 119,
- /* 950 */ 119, 120, 120, 120, 120, 981, 327, 1146, 330, 980,
- /* 960 */ 121, 110, 112, 1169, 1169, 1010, 1013, 1003, 1003, 119,
- /* 970 */ 119, 120, 120, 120, 120, 468, 381, 1189, 118, 118,
- /* 980 */ 118, 118, 117, 117, 116, 116, 116, 115, 428, 1146,
- /* 990 */ 980, 980, 982, 309, 9, 370, 244, 366, 118, 118,
- /* 1000 */ 118, 118, 117, 117, 116, 116, 116, 115, 428, 317,
- /* 1010 */ 550, 348, 1146, 1147, 1148, 299, 290, 541, 118, 118,
- /* 1020 */ 118, 118, 117, 117, 116, 116, 116, 115, 428, 1267,
- /* 1030 */ 1267, 1167, 13, 13, 278, 425, 424, 472, 396, 927,
- /* 1040 */ 260, 260, 289, 1173, 1146, 1147, 1148, 189, 1175, 266,
- /* 1050 */ 266, 472, 394, 547, 1190, 550, 1174, 263, 144, 493,
- /* 1060 */ 926, 550, 547, 122, 112, 1169, 1169, 1010, 1013, 1003,
- /* 1070 */ 1003, 119, 119, 120, 120, 120, 120, 71, 71, 1146,
- /* 1080 */ 1176, 1276, 1176, 13, 13, 902, 1074, 1167, 550, 472,
- /* 1090 */ 901, 107, 542, 1495, 4, 1272, 1113, 6, 529, 1053,
- /* 1100 */ 12, 1075, 1096, 1574, 316, 459, 1574, 524, 545, 1113,
- /* 1110 */ 56, 56, 1113, 1493, 427, 1362, 1076, 6, 349, 285,
- /* 1120 */ 118, 118, 118, 118, 117, 117, 116, 116, 116, 115,
- /* 1130 */ 428, 429, 1275, 325, 1146, 1147, 1148, 882, 266, 266,
- /* 1140 */ 1281, 107, 542, 539, 4, 1492, 293, 883, 1215, 6,
- /* 1150 */ 210, 547, 547, 164, 294, 500, 420, 204, 545, 267,
- /* 1160 */ 267, 1218, 402, 515, 503, 204, 266, 266, 400, 535,
- /* 1170 */ 8, 990, 547, 523, 550, 926, 462, 105, 105, 547,
- /* 1180 */ 1094, 429, 266, 266, 106, 421, 429, 552, 551, 266,
- /* 1190 */ 266, 980, 522, 539, 1377, 547, 15, 15, 266, 266,
- /* 1200 */ 460, 1124, 547, 266, 266, 1074, 1376, 519, 290, 541,
- /* 1210 */ 550, 547, 518, 97, 448, 320, 547, 550, 926, 125,
- /* 1220 */ 1075, 990, 980, 980, 982, 983, 27, 105, 105, 405,
- /* 1230 */ 347, 1515, 44, 44, 106, 1076, 429, 552, 551, 57,
- /* 1240 */ 57, 980, 347, 1515, 107, 542, 550, 4, 466, 405,
- /* 1250 */ 214, 1124, 463, 297, 381, 1095, 538, 1313, 550, 543,
- /* 1260 */ 402, 545, 290, 541, 104, 244, 102, 530, 58, 58,
- /* 1270 */ 550, 199, 980, 980, 982, 983, 27, 1520, 1135, 431,
- /* 1280 */ 59, 59, 270, 237, 429, 138, 95, 379, 379, 378,
- /* 1290 */ 255, 376, 60, 60, 821, 1184, 539, 550, 273, 550,
- /* 1300 */ 1167, 1312, 393, 392, 550, 442, 550, 215, 210, 296,
- /* 1310 */ 519, 853, 550, 265, 208, 520, 1480, 295, 274, 61,
- /* 1320 */ 61, 62, 62, 312, 990, 109, 45, 45, 46, 46,
- /* 1330 */ 105, 105, 1190, 926, 47, 47, 345, 106, 550, 429,
- /* 1340 */ 552, 551, 1546, 550, 980, 871, 344, 217, 550, 941,
- /* 1350 */ 401, 107, 542, 218, 4, 156, 1167, 942, 158, 550,
- /* 1360 */ 49, 49, 1166, 550, 268, 50, 50, 550, 545, 1454,
- /* 1370 */ 63, 63, 550, 1453, 216, 980, 980, 982, 983, 27,
- /* 1380 */ 450, 64, 64, 550, 464, 65, 65, 550, 322, 14,
- /* 1390 */ 14, 429, 1309, 550, 66, 66, 1091, 550, 141, 383,
- /* 1400 */ 38, 550, 967, 539, 326, 127, 127, 550, 397, 67,
- /* 1410 */ 67, 550, 329, 290, 541, 52, 52, 519, 550, 68,
- /* 1420 */ 68, 849, 518, 69, 69, 403, 165, 861, 860, 53,
- /* 1430 */ 53, 990, 315, 151, 151, 97, 436, 105, 105, 331,
- /* 1440 */ 152, 152, 530, 1052, 106, 1052, 429, 552, 551, 1135,
- /* 1450 */ 431, 980, 1036, 270, 972, 239, 333, 243, 379, 379,
- /* 1460 */ 378, 255, 376, 944, 945, 821, 1300, 550, 220, 550,
- /* 1470 */ 107, 542, 550, 4, 550, 1260, 199, 849, 215, 1040,
- /* 1480 */ 296, 1534, 980, 980, 982, 983, 27, 545, 295, 76,
- /* 1490 */ 76, 54, 54, 984, 72, 72, 128, 128, 868, 869,
- /* 1500 */ 107, 542, 550, 4, 1051, 550, 1051, 537, 473, 550,
- /* 1510 */ 429, 550, 454, 1244, 550, 243, 550, 545, 217, 550,
- /* 1520 */ 456, 197, 539, 243, 73, 73, 156, 129, 129, 158,
- /* 1530 */ 340, 130, 130, 126, 126, 1040, 150, 150, 149, 149,
- /* 1540 */ 429, 134, 134, 321, 478, 216, 97, 239, 335, 984,
- /* 1550 */ 990, 97, 539, 350, 351, 550, 105, 105, 906, 935,
- /* 1560 */ 550, 899, 243, 106, 109, 429, 552, 551, 550, 1509,
- /* 1570 */ 980, 832, 99, 542, 139, 4, 550, 133, 133, 397,
- /* 1580 */ 990, 1321, 131, 131, 290, 541, 105, 105, 1361, 545,
- /* 1590 */ 132, 132, 1296, 106, 1307, 429, 552, 551, 75, 75,
- /* 1600 */ 980, 980, 980, 982, 983, 27, 550, 436, 900, 1293,
- /* 1610 */ 536, 109, 429, 1367, 550, 1225, 1217, 1206, 258, 550,
- /* 1620 */ 353, 550, 1205, 11, 539, 1207, 1528, 355, 77, 77,
- /* 1630 */ 380, 980, 980, 982, 983, 27, 74, 74, 357, 213,
- /* 1640 */ 303, 43, 43, 48, 48, 441, 314, 201, 307, 1354,
- /* 1650 */ 319, 359, 990, 458, 483, 1243, 343, 192, 105, 105,
- /* 1660 */ 1426, 1425, 193, 540, 205, 106, 1531, 429, 552, 551,
- /* 1670 */ 1184, 167, 980, 270, 247, 1473, 1471, 1181, 379, 379,
- /* 1680 */ 378, 255, 376, 200, 373, 821, 404, 83, 79, 82,
- /* 1690 */ 1431, 452, 177, 124, 530, 1346, 95, 301, 215, 302,
- /* 1700 */ 296, 161, 169, 980, 980, 982, 983, 27, 295, 1343,
- /* 1710 */ 305, 306, 444, 445, 1351, 172, 35, 173, 174, 175,
- /* 1720 */ 476, 223, 387, 385, 36, 451, 465, 1357, 181, 388,
- /* 1730 */ 88, 471, 227, 1420, 186, 474, 259, 1442, 217, 229,
- /* 1740 */ 230, 324, 328, 390, 492, 231, 156, 1263, 1208, 158,
- /* 1750 */ 417, 1254, 90, 853, 1262, 1261, 206, 419, 1514, 511,
- /* 1760 */ 1304, 94, 1545, 352, 354, 216, 1305, 1303, 283, 1233,
- /* 1770 */ 284, 391, 1232, 1544, 342, 1231, 1543, 356, 245, 1302,
- /* 1780 */ 1253, 502, 505, 358, 246, 1500, 1499, 422, 10, 367,
- /* 1790 */ 101, 1328, 1327, 514, 1406, 96, 253, 1214, 34, 397,
- /* 1800 */ 553, 1141, 254, 365, 290, 541, 256, 257, 554, 1286,
- /* 1810 */ 372, 196, 1285, 371, 1203, 1198, 153, 1458, 137, 1459,
- /* 1820 */ 154, 1457, 281, 1456, 155, 808, 430, 436, 202, 398,
- /* 1830 */ 203, 78, 288, 198, 292, 212, 271, 1050, 135, 1048,
- /* 1840 */ 964, 157, 219, 168, 170, 885, 313, 1064, 222, 176,
- /* 1850 */ 968, 159, 406, 84, 408, 178, 85, 86, 87, 160,
- /* 1860 */ 1067, 224, 1063, 225, 146, 166, 399, 18, 226, 323,
- /* 1870 */ 1056, 1178, 470, 243, 182, 228, 183, 37, 823, 475,
- /* 1880 */ 344, 232, 479, 487, 184, 89, 19, 851, 336, 20,
- /* 1890 */ 339, 484, 91, 282, 162, 147, 864, 92, 494, 93,
- /* 1900 */ 1129, 148, 1016, 1099, 39, 501, 1100, 40, 504, 207,
- /* 1910 */ 262, 264, 934, 187, 929, 109, 1119, 1115, 1117, 7,
- /* 1920 */ 242, 1103, 33, 1123, 21, 526, 22, 23, 24, 1122,
- /* 1930 */ 25, 190, 97, 26, 1031, 1017, 1015, 1019, 1073, 1020,
- /* 1940 */ 1072, 249, 248, 28, 41, 895, 985, 833, 108, 29,
- /* 1950 */ 377, 546, 250, 374, 1137, 1136, 1194, 1194, 251, 1194,
- /* 1960 */ 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194, 1194,
- /* 1970 */ 1194, 1194, 1536, 1535,
+ /* 0 */ 572, 208, 572, 118, 115, 229, 572, 118, 115, 229,
+ /* 10 */ 572, 1318, 381, 1297, 412, 566, 566, 566, 572, 413,
+ /* 20 */ 382, 1318, 1280, 41, 41, 41, 41, 208, 1530, 71,
+ /* 30 */ 71, 975, 423, 41, 41, 495, 303, 279, 303, 976,
+ /* 40 */ 401, 71, 71, 125, 126, 80, 1221, 1221, 1054, 1057,
+ /* 50 */ 1044, 1044, 123, 123, 124, 124, 124, 124, 480, 413,
+ /* 60 */ 1245, 1, 1, 579, 2, 1249, 554, 118, 115, 229,
+ /* 70 */ 317, 484, 146, 484, 528, 118, 115, 229, 533, 1331,
+ /* 80 */ 421, 527, 142, 125, 126, 80, 1221, 1221, 1054, 1057,
+ /* 90 */ 1044, 1044, 123, 123, 124, 124, 124, 124, 118, 115,
+ /* 100 */ 229, 327, 122, 122, 122, 122, 121, 121, 120, 120,
+ /* 110 */ 120, 119, 116, 448, 284, 284, 284, 284, 446, 446,
+ /* 120 */ 446, 1571, 380, 1573, 1196, 379, 1167, 569, 1167, 569,
+ /* 130 */ 413, 1571, 541, 259, 226, 448, 101, 145, 453, 316,
+ /* 140 */ 563, 240, 122, 122, 122, 122, 121, 121, 120, 120,
+ /* 150 */ 120, 119, 116, 448, 125, 126, 80, 1221, 1221, 1054,
+ /* 160 */ 1057, 1044, 1044, 123, 123, 124, 124, 124, 124, 142,
+ /* 170 */ 294, 1196, 343, 452, 120, 120, 120, 119, 116, 448,
+ /* 180 */ 127, 1196, 1197, 1198, 148, 445, 444, 572, 119, 116,
+ /* 190 */ 448, 124, 124, 124, 124, 117, 122, 122, 122, 122,
+ /* 200 */ 121, 121, 120, 120, 120, 119, 116, 448, 458, 113,
+ /* 210 */ 13, 13, 550, 122, 122, 122, 122, 121, 121, 120,
+ /* 220 */ 120, 120, 119, 116, 448, 426, 316, 563, 1196, 1197,
+ /* 230 */ 1198, 149, 1228, 413, 1228, 124, 124, 124, 124, 122,
+ /* 240 */ 122, 122, 122, 121, 121, 120, 120, 120, 119, 116,
+ /* 250 */ 448, 469, 346, 1041, 1041, 1055, 1058, 125, 126, 80,
+ /* 260 */ 1221, 1221, 1054, 1057, 1044, 1044, 123, 123, 124, 124,
+ /* 270 */ 124, 124, 1283, 526, 222, 1196, 572, 413, 224, 518,
+ /* 280 */ 175, 82, 83, 122, 122, 122, 122, 121, 121, 120,
+ /* 290 */ 120, 120, 119, 116, 448, 1011, 16, 16, 1196, 133,
+ /* 300 */ 133, 125, 126, 80, 1221, 1221, 1054, 1057, 1044, 1044,
+ /* 310 */ 123, 123, 124, 124, 124, 124, 122, 122, 122, 122,
+ /* 320 */ 121, 121, 120, 120, 120, 119, 116, 448, 1045, 550,
+ /* 330 */ 1196, 377, 1196, 1197, 1198, 252, 1438, 403, 508, 505,
+ /* 340 */ 504, 111, 564, 570, 4, 930, 930, 437, 503, 344,
+ /* 350 */ 464, 330, 364, 398, 1241, 1196, 1197, 1198, 567, 572,
+ /* 360 */ 122, 122, 122, 122, 121, 121, 120, 120, 120, 119,
+ /* 370 */ 116, 448, 284, 284, 373, 1584, 1611, 445, 444, 154,
+ /* 380 */ 413, 449, 71, 71, 1290, 569, 1225, 1196, 1197, 1198,
+ /* 390 */ 85, 1227, 271, 561, 547, 519, 1565, 572, 98, 1226,
+ /* 400 */ 6, 1282, 476, 142, 125, 126, 80, 1221, 1221, 1054,
+ /* 410 */ 1057, 1044, 1044, 123, 123, 124, 124, 124, 124, 554,
+ /* 420 */ 13, 13, 1031, 511, 1228, 1196, 1228, 553, 109, 109,
+ /* 430 */ 222, 572, 1242, 175, 572, 431, 110, 197, 449, 574,
+ /* 440 */ 573, 434, 1556, 1021, 325, 555, 1196, 270, 287, 372,
+ /* 450 */ 514, 367, 513, 257, 71, 71, 547, 71, 71, 363,
+ /* 460 */ 316, 563, 1617, 122, 122, 122, 122, 121, 121, 120,
+ /* 470 */ 120, 120, 119, 116, 448, 1021, 1021, 1023, 1024, 27,
+ /* 480 */ 284, 284, 1196, 1197, 1198, 1162, 572, 1616, 413, 905,
+ /* 490 */ 190, 554, 360, 569, 554, 941, 537, 521, 1162, 520,
+ /* 500 */ 417, 1162, 556, 1196, 1197, 1198, 572, 548, 1558, 51,
+ /* 510 */ 51, 214, 125, 126, 80, 1221, 1221, 1054, 1057, 1044,
+ /* 520 */ 1044, 123, 123, 124, 124, 124, 124, 1196, 478, 135,
+ /* 530 */ 135, 413, 284, 284, 1494, 509, 121, 121, 120, 120,
+ /* 540 */ 120, 119, 116, 448, 1011, 569, 522, 217, 545, 1565,
+ /* 550 */ 316, 563, 142, 6, 536, 125, 126, 80, 1221, 1221,
+ /* 560 */ 1054, 1057, 1044, 1044, 123, 123, 124, 124, 124, 124,
+ /* 570 */ 1559, 122, 122, 122, 122, 121, 121, 120, 120, 120,
+ /* 580 */ 119, 116, 448, 489, 1196, 1197, 1198, 486, 281, 1271,
+ /* 590 */ 961, 252, 1196, 377, 508, 505, 504, 1196, 344, 575,
+ /* 600 */ 1196, 575, 413, 292, 503, 961, 880, 191, 484, 316,
+ /* 610 */ 563, 388, 290, 384, 122, 122, 122, 122, 121, 121,
+ /* 620 */ 120, 120, 120, 119, 116, 448, 125, 126, 80, 1221,
+ /* 630 */ 1221, 1054, 1057, 1044, 1044, 123, 123, 124, 124, 124,
+ /* 640 */ 124, 413, 398, 1140, 1196, 873, 100, 284, 284, 1196,
+ /* 650 */ 1197, 1198, 377, 1097, 1196, 1197, 1198, 1196, 1197, 1198,
+ /* 660 */ 569, 459, 32, 377, 233, 125, 126, 80, 1221, 1221,
+ /* 670 */ 1054, 1057, 1044, 1044, 123, 123, 124, 124, 124, 124,
+ /* 680 */ 1437, 963, 572, 228, 962, 122, 122, 122, 122, 121,
+ /* 690 */ 121, 120, 120, 120, 119, 116, 448, 1162, 228, 1196,
+ /* 700 */ 157, 1196, 1197, 1198, 1557, 13, 13, 301, 961, 1236,
+ /* 710 */ 1162, 153, 413, 1162, 377, 1587, 1180, 5, 373, 1584,
+ /* 720 */ 433, 1242, 3, 961, 122, 122, 122, 122, 121, 121,
+ /* 730 */ 120, 120, 120, 119, 116, 448, 125, 126, 80, 1221,
+ /* 740 */ 1221, 1054, 1057, 1044, 1044, 123, 123, 124, 124, 124,
+ /* 750 */ 124, 413, 208, 571, 1196, 1032, 1196, 1197, 1198, 1196,
+ /* 760 */ 392, 856, 155, 1556, 286, 406, 1102, 1102, 492, 572,
+ /* 770 */ 469, 346, 1323, 1323, 1556, 125, 126, 80, 1221, 1221,
+ /* 780 */ 1054, 1057, 1044, 1044, 123, 123, 124, 124, 124, 124,
+ /* 790 */ 129, 572, 13, 13, 378, 122, 122, 122, 122, 121,
+ /* 800 */ 121, 120, 120, 120, 119, 116, 448, 302, 572, 457,
+ /* 810 */ 532, 1196, 1197, 1198, 13, 13, 1196, 1197, 1198, 1301,
+ /* 820 */ 467, 1271, 413, 1321, 1321, 1556, 1016, 457, 456, 200,
+ /* 830 */ 299, 71, 71, 1269, 122, 122, 122, 122, 121, 121,
+ /* 840 */ 120, 120, 120, 119, 116, 448, 125, 126, 80, 1221,
+ /* 850 */ 1221, 1054, 1057, 1044, 1044, 123, 123, 124, 124, 124,
+ /* 860 */ 124, 413, 227, 1077, 1162, 284, 284, 423, 312, 278,
+ /* 870 */ 278, 285, 285, 1423, 410, 409, 386, 1162, 569, 572,
+ /* 880 */ 1162, 1200, 569, 1604, 569, 125, 126, 80, 1221, 1221,
+ /* 890 */ 1054, 1057, 1044, 1044, 123, 123, 124, 124, 124, 124,
+ /* 900 */ 457, 1486, 13, 13, 1540, 122, 122, 122, 122, 121,
+ /* 910 */ 121, 120, 120, 120, 119, 116, 448, 201, 572, 358,
+ /* 920 */ 1590, 579, 2, 1249, 844, 845, 846, 1566, 317, 1216,
+ /* 930 */ 146, 6, 413, 255, 254, 253, 206, 1331, 9, 1200,
+ /* 940 */ 262, 71, 71, 428, 122, 122, 122, 122, 121, 121,
+ /* 950 */ 120, 120, 120, 119, 116, 448, 125, 126, 80, 1221,
+ /* 960 */ 1221, 1054, 1057, 1044, 1044, 123, 123, 124, 124, 124,
+ /* 970 */ 124, 572, 284, 284, 572, 1217, 413, 578, 313, 1249,
+ /* 980 */ 353, 1300, 356, 423, 317, 569, 146, 495, 529, 1647,
+ /* 990 */ 399, 375, 495, 1331, 70, 70, 1299, 71, 71, 240,
+ /* 1000 */ 1329, 104, 80, 1221, 1221, 1054, 1057, 1044, 1044, 123,
+ /* 1010 */ 123, 124, 124, 124, 124, 122, 122, 122, 122, 121,
+ /* 1020 */ 121, 120, 120, 120, 119, 116, 448, 1118, 284, 284,
+ /* 1030 */ 432, 452, 1529, 1217, 443, 284, 284, 1493, 1356, 311,
+ /* 1040 */ 478, 569, 1119, 975, 495, 495, 217, 1267, 569, 1542,
+ /* 1050 */ 572, 976, 207, 572, 1031, 240, 387, 1120, 523, 122,
+ /* 1060 */ 122, 122, 122, 121, 121, 120, 120, 120, 119, 116,
+ /* 1070 */ 448, 1022, 107, 71, 71, 1021, 13, 13, 916, 572,
+ /* 1080 */ 1499, 572, 284, 284, 97, 530, 495, 452, 917, 1330,
+ /* 1090 */ 1326, 549, 413, 284, 284, 569, 151, 209, 1499, 1501,
+ /* 1100 */ 262, 454, 55, 55, 56, 56, 569, 1021, 1021, 1023,
+ /* 1110 */ 447, 336, 413, 531, 12, 295, 125, 126, 80, 1221,
+ /* 1120 */ 1221, 1054, 1057, 1044, 1044, 123, 123, 124, 124, 124,
+ /* 1130 */ 124, 351, 413, 868, 1538, 1217, 125, 126, 80, 1221,
+ /* 1140 */ 1221, 1054, 1057, 1044, 1044, 123, 123, 124, 124, 124,
+ /* 1150 */ 124, 1141, 1645, 478, 1645, 375, 125, 114, 80, 1221,
+ /* 1160 */ 1221, 1054, 1057, 1044, 1044, 123, 123, 124, 124, 124,
+ /* 1170 */ 124, 1499, 333, 478, 335, 122, 122, 122, 122, 121,
+ /* 1180 */ 121, 120, 120, 120, 119, 116, 448, 203, 1423, 572,
+ /* 1190 */ 1298, 868, 468, 1217, 440, 122, 122, 122, 122, 121,
+ /* 1200 */ 121, 120, 120, 120, 119, 116, 448, 557, 1141, 1646,
+ /* 1210 */ 543, 1646, 15, 15, 896, 122, 122, 122, 122, 121,
+ /* 1220 */ 121, 120, 120, 120, 119, 116, 448, 572, 298, 542,
+ /* 1230 */ 1139, 1423, 1563, 1564, 1335, 413, 6, 6, 1173, 1272,
+ /* 1240 */ 419, 320, 284, 284, 1423, 512, 569, 529, 300, 461,
+ /* 1250 */ 43, 43, 572, 897, 12, 569, 334, 482, 429, 411,
+ /* 1260 */ 126, 80, 1221, 1221, 1054, 1057, 1044, 1044, 123, 123,
+ /* 1270 */ 124, 124, 124, 124, 572, 57, 57, 288, 1196, 1423,
+ /* 1280 */ 500, 462, 396, 396, 395, 273, 393, 1139, 1562, 853,
+ /* 1290 */ 1173, 411, 6, 572, 321, 1162, 474, 44, 44, 1561,
+ /* 1300 */ 1118, 430, 234, 6, 323, 256, 544, 256, 1162, 435,
+ /* 1310 */ 572, 1162, 322, 17, 491, 1119, 58, 58, 122, 122,
+ /* 1320 */ 122, 122, 121, 121, 120, 120, 120, 119, 116, 448,
+ /* 1330 */ 1120, 216, 485, 59, 59, 1196, 1197, 1198, 111, 564,
+ /* 1340 */ 324, 4, 236, 460, 530, 572, 237, 460, 572, 441,
+ /* 1350 */ 168, 560, 424, 141, 483, 567, 572, 293, 572, 1099,
+ /* 1360 */ 572, 293, 572, 1099, 535, 572, 876, 8, 60, 60,
+ /* 1370 */ 235, 61, 61, 572, 418, 572, 418, 572, 449, 62,
+ /* 1380 */ 62, 45, 45, 46, 46, 47, 47, 199, 49, 49,
+ /* 1390 */ 561, 572, 363, 572, 100, 490, 50, 50, 63, 63,
+ /* 1400 */ 64, 64, 565, 419, 539, 414, 572, 1031, 572, 538,
+ /* 1410 */ 316, 563, 316, 563, 65, 65, 14, 14, 572, 1031,
+ /* 1420 */ 572, 516, 936, 876, 1022, 109, 109, 935, 1021, 66,
+ /* 1430 */ 66, 131, 131, 110, 455, 449, 574, 573, 420, 177,
+ /* 1440 */ 1021, 132, 132, 67, 67, 572, 471, 572, 936, 475,
+ /* 1450 */ 1368, 283, 226, 935, 315, 1367, 411, 572, 463, 411,
+ /* 1460 */ 1021, 1021, 1023, 239, 411, 86, 213, 1354, 52, 52,
+ /* 1470 */ 68, 68, 1021, 1021, 1023, 1024, 27, 1589, 1184, 451,
+ /* 1480 */ 69, 69, 288, 97, 108, 1545, 106, 396, 396, 395,
+ /* 1490 */ 273, 393, 572, 883, 853, 887, 572, 111, 564, 470,
+ /* 1500 */ 4, 572, 152, 30, 38, 572, 1136, 234, 400, 323,
+ /* 1510 */ 111, 564, 531, 4, 567, 53, 53, 322, 572, 163,
+ /* 1520 */ 163, 572, 341, 472, 164, 164, 337, 567, 76, 76,
+ /* 1530 */ 572, 289, 1518, 572, 31, 1517, 572, 449, 342, 487,
+ /* 1540 */ 100, 54, 54, 348, 72, 72, 296, 236, 1084, 561,
+ /* 1550 */ 449, 883, 1364, 134, 134, 168, 73, 73, 141, 161,
+ /* 1560 */ 161, 1578, 561, 539, 572, 319, 572, 352, 540, 1013,
+ /* 1570 */ 477, 261, 261, 895, 894, 235, 539, 572, 1031, 572,
+ /* 1580 */ 479, 538, 261, 371, 109, 109, 525, 136, 136, 130,
+ /* 1590 */ 130, 1031, 110, 370, 449, 574, 573, 109, 109, 1021,
+ /* 1600 */ 162, 162, 156, 156, 572, 110, 1084, 449, 574, 573,
+ /* 1610 */ 414, 355, 1021, 572, 357, 316, 563, 572, 347, 572,
+ /* 1620 */ 100, 501, 361, 258, 100, 902, 903, 140, 140, 359,
+ /* 1630 */ 1314, 1021, 1021, 1023, 1024, 27, 139, 139, 366, 455,
+ /* 1640 */ 137, 137, 138, 138, 1021, 1021, 1023, 1024, 27, 1184,
+ /* 1650 */ 451, 572, 376, 288, 111, 564, 1025, 4, 396, 396,
+ /* 1660 */ 395, 273, 393, 572, 1145, 853, 572, 1080, 572, 258,
+ /* 1670 */ 496, 567, 572, 211, 75, 75, 559, 966, 234, 261,
+ /* 1680 */ 323, 111, 564, 933, 4, 113, 77, 77, 322, 74,
+ /* 1690 */ 74, 42, 42, 1377, 449, 48, 48, 1422, 567, 978,
+ /* 1700 */ 979, 1096, 1095, 1096, 1095, 866, 561, 150, 934, 1350,
+ /* 1710 */ 113, 1362, 558, 1428, 1025, 1279, 1270, 1258, 236, 1257,
+ /* 1720 */ 1259, 449, 1597, 1347, 308, 276, 168, 309, 11, 141,
+ /* 1730 */ 397, 310, 232, 561, 1409, 1031, 339, 291, 329, 219,
+ /* 1740 */ 340, 109, 109, 940, 297, 1414, 235, 345, 481, 110,
+ /* 1750 */ 506, 449, 574, 573, 332, 1413, 1021, 404, 1297, 369,
+ /* 1760 */ 223, 1490, 1031, 1489, 1359, 1360, 1358, 1357, 109, 109,
+ /* 1770 */ 204, 1600, 1236, 562, 265, 218, 110, 205, 449, 574,
+ /* 1780 */ 573, 414, 391, 1021, 1537, 179, 316, 563, 1021, 1021,
+ /* 1790 */ 1023, 1024, 27, 230, 1535, 1233, 79, 564, 85, 4,
+ /* 1800 */ 422, 215, 552, 81, 84, 188, 1410, 128, 1404, 550,
+ /* 1810 */ 455, 35, 328, 567, 173, 1021, 1021, 1023, 1024, 27,
+ /* 1820 */ 181, 1495, 1397, 331, 465, 183, 184, 185, 186, 466,
+ /* 1830 */ 499, 242, 98, 402, 1416, 1418, 449, 1415, 473, 36,
+ /* 1840 */ 192, 488, 405, 1506, 246, 91, 494, 196, 561, 1484,
+ /* 1850 */ 350, 497, 277, 354, 248, 249, 111, 564, 1260, 4,
+ /* 1860 */ 250, 407, 515, 436, 1317, 1308, 93, 1316, 1315, 887,
+ /* 1870 */ 1307, 224, 1583, 567, 438, 524, 439, 1031, 263, 264,
+ /* 1880 */ 442, 1615, 10, 109, 109, 1287, 408, 1614, 1286, 368,
+ /* 1890 */ 1285, 110, 1613, 449, 574, 573, 449, 306, 1021, 307,
+ /* 1900 */ 374, 1382, 1569, 1470, 1381, 385, 105, 314, 561, 99,
+ /* 1910 */ 1568, 534, 34, 576, 1190, 272, 1340, 551, 383, 274,
+ /* 1920 */ 1339, 210, 389, 390, 275, 577, 1255, 1250, 415, 165,
+ /* 1930 */ 1021, 1021, 1023, 1024, 27, 147, 1522, 1031, 166, 1523,
+ /* 1940 */ 416, 1521, 178, 109, 109, 1520, 304, 167, 840, 450,
+ /* 1950 */ 220, 110, 221, 449, 574, 573, 212, 78, 1021, 318,
+ /* 1960 */ 231, 1094, 1092, 144, 180, 326, 169, 1216, 241, 182,
+ /* 1970 */ 919, 338, 238, 1108, 187, 170, 171, 425, 427, 189,
+ /* 1980 */ 87, 88, 89, 90, 172, 1111, 243, 1107, 244, 158,
+ /* 1990 */ 1021, 1021, 1023, 1024, 27, 18, 245, 1230, 493, 349,
+ /* 2000 */ 1100, 261, 247, 193, 194, 37, 370, 855, 498, 251,
+ /* 2010 */ 195, 510, 92, 19, 174, 362, 502, 20, 507, 885,
+ /* 2020 */ 365, 898, 94, 305, 159, 95, 517, 96, 1178, 160,
+ /* 2030 */ 1060, 1147, 39, 1146, 225, 280, 282, 970, 198, 964,
+ /* 2040 */ 113, 1164, 1168, 260, 1166, 21, 1172, 7, 22, 1152,
+ /* 2050 */ 33, 23, 24, 25, 1171, 546, 26, 202, 100, 102,
+ /* 2060 */ 1075, 103, 1061, 1059, 1063, 1117, 1064, 1116, 266, 267,
+ /* 2070 */ 28, 40, 929, 1026, 867, 112, 29, 568, 394, 143,
+ /* 2080 */ 1186, 268, 176, 1185, 269, 1246, 1246, 1246, 1246, 1246,
+ /* 2090 */ 1246, 1246, 1246, 1246, 1246, 1606, 1246, 1246, 1246, 1246,
+ /* 2100 */ 1605,
};
static const YYCODETYPE yy_lookahead[] = {
- /* 0 */ 189, 211, 189, 189, 218, 189, 220, 189, 267, 268,
- /* 10 */ 269, 189, 210, 189, 228, 189, 267, 268, 269, 19,
- /* 20 */ 218, 189, 211, 212, 211, 212, 211, 211, 212, 211,
- /* 30 */ 212, 31, 211, 211, 212, 211, 212, 288, 300, 39,
- /* 40 */ 21, 189, 304, 43, 44, 45, 46, 47, 48, 49,
- /* 50 */ 50, 51, 52, 53, 54, 55, 56, 57, 225, 19,
- /* 60 */ 189, 183, 184, 185, 186, 189, 248, 263, 236, 191,
- /* 70 */ 248, 193, 248, 197, 208, 257, 262, 201, 200, 257,
- /* 80 */ 200, 257, 81, 43, 44, 45, 46, 47, 48, 49,
- /* 90 */ 50, 51, 52, 53, 54, 55, 56, 57, 189, 80,
- /* 100 */ 189, 101, 102, 103, 104, 105, 106, 107, 108, 109,
- /* 110 */ 110, 111, 234, 235, 234, 235, 305, 306, 305, 118,
- /* 120 */ 307, 305, 306, 297, 298, 247, 86, 247, 88, 19,
- /* 130 */ 259, 251, 252, 267, 268, 269, 26, 136, 137, 261,
- /* 140 */ 121, 101, 102, 103, 104, 105, 106, 107, 108, 109,
- /* 150 */ 110, 111, 59, 43, 44, 45, 46, 47, 48, 49,
- /* 160 */ 50, 51, 52, 53, 54, 55, 56, 57, 259, 291,
- /* 170 */ 105, 106, 107, 108, 109, 110, 111, 158, 189, 69,
- /* 180 */ 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
- /* 190 */ 111, 107, 108, 109, 110, 111, 205, 206, 207, 19,
- /* 200 */ 19, 54, 55, 56, 57, 58, 29, 114, 115, 116,
- /* 210 */ 33, 101, 102, 103, 104, 105, 106, 107, 108, 109,
- /* 220 */ 110, 111, 233, 43, 44, 45, 46, 47, 48, 49,
- /* 230 */ 50, 51, 52, 53, 54, 55, 56, 57, 19, 126,
- /* 240 */ 127, 148, 65, 24, 214, 200, 59, 67, 101, 102,
- /* 250 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 22,
- /* 260 */ 189, 111, 43, 44, 45, 46, 47, 48, 49, 50,
- /* 270 */ 51, 52, 53, 54, 55, 56, 57, 206, 207, 234,
- /* 280 */ 235, 101, 102, 103, 104, 105, 106, 107, 108, 109,
- /* 290 */ 110, 111, 247, 76, 107, 114, 59, 267, 268, 269,
- /* 300 */ 189, 114, 115, 116, 162, 163, 89, 19, 263, 92,
- /* 310 */ 189, 23, 54, 55, 56, 57, 189, 206, 207, 22,
- /* 320 */ 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
- /* 330 */ 111, 43, 44, 45, 46, 47, 48, 49, 50, 51,
- /* 340 */ 52, 53, 54, 55, 56, 57, 19, 189, 277, 59,
- /* 350 */ 23, 114, 115, 116, 46, 47, 48, 49, 61, 101,
+ /* 0 */ 193, 193, 193, 274, 275, 276, 193, 274, 275, 276,
+ /* 10 */ 193, 223, 219, 225, 206, 210, 211, 212, 193, 19,
+ /* 20 */ 219, 233, 216, 216, 217, 216, 217, 193, 295, 216,
+ /* 30 */ 217, 31, 193, 216, 217, 193, 228, 213, 230, 39,
+ /* 40 */ 206, 216, 217, 43, 44, 45, 46, 47, 48, 49,
+ /* 50 */ 50, 51, 52, 53, 54, 55, 56, 57, 193, 19,
+ /* 60 */ 185, 186, 187, 188, 189, 190, 253, 274, 275, 276,
+ /* 70 */ 195, 193, 197, 193, 261, 274, 275, 276, 253, 204,
+ /* 80 */ 238, 204, 81, 43, 44, 45, 46, 47, 48, 49,
+ /* 90 */ 50, 51, 52, 53, 54, 55, 56, 57, 274, 275,
+ /* 100 */ 276, 262, 102, 103, 104, 105, 106, 107, 108, 109,
+ /* 110 */ 110, 111, 112, 113, 239, 240, 239, 240, 210, 211,
+ /* 120 */ 212, 314, 315, 314, 59, 316, 86, 252, 88, 252,
+ /* 130 */ 19, 314, 315, 256, 257, 113, 25, 72, 296, 138,
+ /* 140 */ 139, 266, 102, 103, 104, 105, 106, 107, 108, 109,
+ /* 150 */ 110, 111, 112, 113, 43, 44, 45, 46, 47, 48,
+ /* 160 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 81,
+ /* 170 */ 292, 59, 292, 298, 108, 109, 110, 111, 112, 113,
+ /* 180 */ 69, 116, 117, 118, 72, 106, 107, 193, 111, 112,
+ /* 190 */ 113, 54, 55, 56, 57, 58, 102, 103, 104, 105,
+ /* 200 */ 106, 107, 108, 109, 110, 111, 112, 113, 120, 25,
+ /* 210 */ 216, 217, 145, 102, 103, 104, 105, 106, 107, 108,
+ /* 220 */ 109, 110, 111, 112, 113, 231, 138, 139, 116, 117,
+ /* 230 */ 118, 164, 153, 19, 155, 54, 55, 56, 57, 102,
+ /* 240 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
+ /* 250 */ 113, 128, 129, 46, 47, 48, 49, 43, 44, 45,
+ /* 260 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
+ /* 270 */ 56, 57, 216, 193, 25, 59, 193, 19, 165, 166,
+ /* 280 */ 193, 67, 24, 102, 103, 104, 105, 106, 107, 108,
+ /* 290 */ 109, 110, 111, 112, 113, 73, 216, 217, 59, 216,
+ /* 300 */ 217, 43, 44, 45, 46, 47, 48, 49, 50, 51,
+ /* 310 */ 52, 53, 54, 55, 56, 57, 102, 103, 104, 105,
+ /* 320 */ 106, 107, 108, 109, 110, 111, 112, 113, 121, 145,
+ /* 330 */ 59, 193, 116, 117, 118, 119, 273, 204, 122, 123,
+ /* 340 */ 124, 19, 20, 134, 22, 136, 137, 19, 132, 127,
+ /* 350 */ 128, 129, 24, 22, 23, 116, 117, 118, 36, 193,
/* 360 */ 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
- /* 370 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
- /* 380 */ 53, 54, 55, 56, 57, 125, 126, 127, 277, 101,
- /* 390 */ 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
- /* 400 */ 59, 189, 189, 276, 114, 115, 116, 117, 73, 59,
- /* 410 */ 120, 121, 122, 72, 214, 19, 81, 259, 19, 23,
- /* 420 */ 130, 81, 72, 24, 211, 212, 221, 119, 101, 102,
- /* 430 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 43,
- /* 440 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
- /* 450 */ 54, 55, 56, 57, 19, 114, 115, 116, 23, 208,
- /* 460 */ 125, 248, 189, 189, 114, 115, 116, 267, 268, 269,
- /* 470 */ 189, 136, 137, 189, 262, 22, 136, 137, 43, 44,
- /* 480 */ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
- /* 490 */ 55, 56, 57, 189, 95, 211, 212, 101, 102, 103,
- /* 500 */ 104, 105, 106, 107, 108, 109, 110, 111, 59, 189,
- /* 510 */ 111, 189, 59, 76, 294, 295, 117, 118, 119, 120,
- /* 520 */ 121, 122, 123, 19, 87, 189, 89, 23, 129, 92,
- /* 530 */ 279, 227, 248, 22, 189, 284, 101, 102, 103, 104,
- /* 540 */ 105, 106, 107, 108, 109, 110, 111, 43, 44, 45,
- /* 550 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
- /* 560 */ 56, 57, 19, 114, 115, 116, 23, 114, 115, 116,
- /* 570 */ 59, 117, 299, 300, 120, 121, 122, 304, 189, 189,
- /* 580 */ 143, 189, 110, 111, 130, 22, 43, 44, 45, 46,
- /* 590 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
- /* 600 */ 57, 211, 212, 211, 212, 101, 102, 103, 104, 105,
- /* 610 */ 106, 107, 108, 109, 110, 111, 226, 189, 226, 189,
- /* 620 */ 298, 132, 59, 134, 135, 114, 115, 116, 189, 59,
- /* 630 */ 285, 19, 7, 8, 9, 23, 205, 206, 207, 211,
- /* 640 */ 212, 211, 212, 221, 101, 102, 103, 104, 105, 106,
- /* 650 */ 107, 108, 109, 110, 111, 43, 44, 45, 46, 47,
- /* 660 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
- /* 670 */ 19, 181, 182, 183, 184, 185, 186, 114, 115, 116,
- /* 680 */ 189, 191, 133, 193, 114, 115, 116, 138, 299, 300,
- /* 690 */ 200, 22, 201, 304, 43, 44, 45, 46, 47, 48,
- /* 700 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 35,
- /* 710 */ 189, 141, 189, 101, 102, 103, 104, 105, 106, 107,
- /* 720 */ 108, 109, 110, 111, 234, 235, 22, 23, 59, 184,
- /* 730 */ 26, 186, 211, 212, 211, 212, 191, 247, 193, 19,
- /* 740 */ 66, 105, 106, 73, 189, 200, 189, 226, 74, 226,
- /* 750 */ 22, 261, 101, 102, 103, 104, 105, 106, 107, 108,
- /* 760 */ 109, 110, 111, 43, 44, 45, 46, 47, 48, 49,
- /* 770 */ 50, 51, 52, 53, 54, 55, 56, 57, 189, 234,
- /* 780 */ 235, 291, 19, 114, 115, 116, 150, 59, 152, 189,
- /* 790 */ 233, 236, 247, 59, 189, 125, 126, 127, 59, 300,
- /* 800 */ 211, 212, 128, 304, 100, 19, 261, 156, 45, 46,
- /* 810 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
- /* 820 */ 57, 101, 102, 103, 104, 105, 106, 107, 108, 109,
- /* 830 */ 110, 111, 46, 233, 189, 189, 291, 248, 99, 189,
- /* 840 */ 125, 126, 127, 115, 26, 200, 289, 230, 231, 115,
- /* 850 */ 200, 16, 189, 114, 115, 189, 211, 212, 119, 221,
- /* 860 */ 189, 211, 212, 258, 101, 102, 103, 104, 105, 106,
- /* 870 */ 107, 108, 109, 110, 111, 189, 156, 211, 212, 234,
- /* 880 */ 235, 189, 211, 212, 234, 235, 22, 201, 189, 150,
- /* 890 */ 151, 152, 247, 248, 76, 16, 19, 247, 248, 113,
- /* 900 */ 189, 24, 257, 211, 212, 189, 26, 89, 262, 223,
- /* 910 */ 92, 225, 77, 189, 79, 129, 19, 53, 226, 248,
- /* 920 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
- /* 930 */ 53, 54, 55, 56, 57, 236, 19, 271, 189, 99,
- /* 940 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
- /* 950 */ 53, 54, 55, 56, 57, 115, 77, 59, 79, 119,
- /* 960 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
- /* 970 */ 53, 54, 55, 56, 57, 259, 22, 23, 101, 102,
- /* 980 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 59,
- /* 990 */ 150, 151, 152, 158, 22, 244, 24, 246, 101, 102,
- /* 1000 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 285,
- /* 1010 */ 189, 189, 114, 115, 116, 200, 136, 137, 101, 102,
- /* 1020 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 230,
- /* 1030 */ 231, 59, 211, 212, 285, 105, 106, 189, 19, 141,
- /* 1040 */ 234, 235, 239, 113, 114, 115, 116, 226, 118, 234,
- /* 1050 */ 235, 189, 249, 247, 100, 189, 126, 23, 236, 107,
- /* 1060 */ 26, 189, 247, 44, 45, 46, 47, 48, 49, 50,
- /* 1070 */ 51, 52, 53, 54, 55, 56, 57, 211, 212, 59,
- /* 1080 */ 150, 233, 152, 211, 212, 133, 12, 115, 189, 189,
- /* 1090 */ 138, 19, 20, 300, 22, 233, 76, 304, 226, 11,
- /* 1100 */ 208, 27, 22, 23, 200, 19, 26, 87, 36, 89,
- /* 1110 */ 211, 212, 92, 300, 248, 189, 42, 304, 189, 250,
- /* 1120 */ 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
- /* 1130 */ 111, 59, 200, 233, 114, 115, 116, 63, 234, 235,
- /* 1140 */ 235, 19, 20, 71, 22, 300, 189, 73, 200, 304,
- /* 1150 */ 116, 247, 247, 81, 189, 200, 227, 26, 36, 234,
- /* 1160 */ 235, 203, 204, 143, 200, 26, 234, 235, 194, 200,
- /* 1170 */ 48, 99, 247, 66, 189, 141, 284, 105, 106, 247,
- /* 1180 */ 100, 59, 234, 235, 112, 259, 114, 115, 116, 234,
- /* 1190 */ 235, 119, 85, 71, 266, 247, 211, 212, 234, 235,
- /* 1200 */ 114, 94, 247, 234, 235, 12, 266, 85, 136, 137,
- /* 1210 */ 189, 247, 90, 26, 126, 127, 247, 189, 26, 22,
- /* 1220 */ 27, 99, 150, 151, 152, 153, 154, 105, 106, 189,
- /* 1230 */ 302, 303, 211, 212, 112, 42, 114, 115, 116, 211,
- /* 1240 */ 212, 119, 302, 303, 19, 20, 189, 22, 274, 189,
- /* 1250 */ 15, 144, 278, 189, 22, 23, 63, 189, 189, 203,
- /* 1260 */ 204, 36, 136, 137, 155, 24, 157, 143, 211, 212,
- /* 1270 */ 189, 140, 150, 151, 152, 153, 154, 0, 1, 2,
- /* 1280 */ 211, 212, 5, 46, 59, 161, 147, 10, 11, 12,
- /* 1290 */ 13, 14, 211, 212, 17, 60, 71, 189, 258, 189,
- /* 1300 */ 59, 189, 105, 106, 189, 189, 189, 30, 116, 32,
- /* 1310 */ 85, 124, 189, 251, 252, 90, 189, 40, 258, 211,
- /* 1320 */ 212, 211, 212, 189, 99, 26, 211, 212, 211, 212,
- /* 1330 */ 105, 106, 100, 141, 211, 212, 119, 112, 189, 114,
- /* 1340 */ 115, 116, 23, 189, 119, 26, 129, 70, 189, 31,
- /* 1350 */ 113, 19, 20, 24, 22, 78, 115, 39, 81, 189,
- /* 1360 */ 211, 212, 26, 189, 22, 211, 212, 189, 36, 189,
- /* 1370 */ 211, 212, 189, 189, 97, 150, 151, 152, 153, 154,
- /* 1380 */ 127, 211, 212, 189, 189, 211, 212, 189, 189, 211,
- /* 1390 */ 212, 59, 189, 189, 211, 212, 23, 189, 22, 26,
- /* 1400 */ 24, 189, 149, 71, 189, 211, 212, 189, 131, 211,
- /* 1410 */ 212, 189, 189, 136, 137, 211, 212, 85, 189, 211,
- /* 1420 */ 212, 59, 90, 211, 212, 292, 293, 118, 119, 211,
- /* 1430 */ 212, 99, 23, 211, 212, 26, 159, 105, 106, 189,
- /* 1440 */ 211, 212, 143, 150, 112, 152, 114, 115, 116, 1,
- /* 1450 */ 2, 119, 23, 5, 23, 26, 189, 26, 10, 11,
- /* 1460 */ 12, 13, 14, 83, 84, 17, 253, 189, 139, 189,
- /* 1470 */ 19, 20, 189, 22, 189, 189, 140, 115, 30, 59,
- /* 1480 */ 32, 139, 150, 151, 152, 153, 154, 36, 40, 211,
- /* 1490 */ 212, 211, 212, 59, 211, 212, 211, 212, 7, 8,
- /* 1500 */ 19, 20, 189, 22, 150, 189, 152, 231, 281, 189,
- /* 1510 */ 59, 189, 23, 189, 189, 26, 189, 36, 70, 189,
- /* 1520 */ 23, 237, 71, 26, 211, 212, 78, 211, 212, 81,
- /* 1530 */ 189, 211, 212, 211, 212, 115, 211, 212, 211, 212,
- /* 1540 */ 59, 211, 212, 23, 23, 97, 26, 26, 23, 115,
- /* 1550 */ 99, 26, 71, 189, 189, 189, 105, 106, 107, 23,
- /* 1560 */ 189, 23, 26, 112, 26, 114, 115, 116, 189, 309,
- /* 1570 */ 119, 23, 19, 20, 26, 22, 189, 211, 212, 131,
- /* 1580 */ 99, 189, 211, 212, 136, 137, 105, 106, 189, 36,
- /* 1590 */ 211, 212, 189, 112, 189, 114, 115, 116, 211, 212,
- /* 1600 */ 119, 150, 151, 152, 153, 154, 189, 159, 23, 250,
- /* 1610 */ 189, 26, 59, 189, 189, 189, 189, 189, 280, 189,
- /* 1620 */ 250, 189, 189, 238, 71, 189, 189, 250, 211, 212,
- /* 1630 */ 187, 150, 151, 152, 153, 154, 211, 212, 250, 290,
- /* 1640 */ 240, 211, 212, 211, 212, 254, 286, 209, 254, 241,
- /* 1650 */ 240, 254, 99, 286, 215, 220, 214, 244, 105, 106,
- /* 1660 */ 214, 214, 244, 273, 224, 112, 192, 114, 115, 116,
- /* 1670 */ 60, 290, 119, 5, 139, 196, 196, 38, 10, 11,
- /* 1680 */ 12, 13, 14, 238, 240, 17, 196, 148, 287, 287,
- /* 1690 */ 276, 113, 22, 146, 143, 245, 147, 244, 30, 241,
- /* 1700 */ 32, 43, 229, 150, 151, 152, 153, 154, 40, 245,
- /* 1710 */ 244, 241, 18, 196, 265, 232, 264, 232, 232, 232,
- /* 1720 */ 18, 195, 265, 241, 264, 241, 196, 229, 229, 241,
- /* 1730 */ 155, 62, 195, 241, 22, 216, 196, 283, 70, 195,
- /* 1740 */ 195, 282, 196, 216, 113, 195, 78, 213, 196, 81,
- /* 1750 */ 64, 222, 22, 124, 213, 213, 162, 111, 303, 142,
- /* 1760 */ 256, 113, 219, 255, 255, 97, 256, 256, 275, 213,
- /* 1770 */ 275, 216, 215, 219, 213, 213, 213, 255, 196, 256,
- /* 1780 */ 222, 216, 216, 255, 91, 308, 308, 82, 22, 196,
- /* 1790 */ 155, 260, 260, 144, 270, 145, 25, 199, 26, 131,
- /* 1800 */ 198, 13, 190, 244, 136, 137, 190, 6, 188, 245,
- /* 1810 */ 241, 243, 245, 242, 188, 188, 202, 208, 217, 208,
- /* 1820 */ 202, 208, 217, 208, 202, 4, 3, 159, 209, 296,
- /* 1830 */ 209, 208, 272, 22, 160, 15, 98, 23, 16, 23,
- /* 1840 */ 137, 128, 24, 148, 140, 20, 16, 1, 142, 140,
- /* 1850 */ 149, 128, 61, 53, 37, 148, 53, 53, 53, 128,
- /* 1860 */ 114, 34, 1, 139, 5, 293, 296, 22, 113, 158,
- /* 1870 */ 68, 75, 41, 26, 68, 139, 113, 24, 20, 19,
- /* 1880 */ 129, 123, 67, 96, 22, 22, 22, 59, 23, 22,
- /* 1890 */ 24, 67, 22, 67, 37, 23, 28, 147, 22, 26,
- /* 1900 */ 23, 23, 23, 23, 22, 24, 23, 22, 24, 139,
- /* 1910 */ 23, 23, 114, 22, 141, 26, 75, 88, 86, 44,
- /* 1920 */ 34, 23, 22, 75, 34, 24, 34, 34, 34, 93,
- /* 1930 */ 34, 26, 26, 34, 23, 23, 23, 23, 23, 11,
- /* 1940 */ 23, 22, 26, 22, 22, 133, 23, 23, 22, 22,
- /* 1950 */ 15, 26, 139, 23, 1, 1, 310, 310, 139, 310,
- /* 1960 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
- /* 1970 */ 310, 310, 139, 139, 310, 310, 310, 310, 310, 310,
- /* 1980 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
- /* 1990 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
- /* 2000 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
- /* 2010 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
- /* 2020 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
- /* 2030 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
- /* 2040 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
- /* 2050 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
- /* 2060 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
- /* 2070 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
- /* 2080 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
- /* 2090 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
- /* 2100 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
- /* 2110 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
- /* 2120 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
- /* 2130 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
- /* 2140 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
- /* 2150 */ 310, 310, 310, 310, 310,
+ /* 370 */ 112, 113, 239, 240, 311, 312, 215, 106, 107, 241,
+ /* 380 */ 19, 59, 216, 217, 223, 252, 115, 116, 117, 118,
+ /* 390 */ 151, 120, 26, 71, 193, 308, 309, 193, 149, 128,
+ /* 400 */ 313, 216, 269, 81, 43, 44, 45, 46, 47, 48,
+ /* 410 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 253,
+ /* 420 */ 216, 217, 100, 95, 153, 59, 155, 261, 106, 107,
+ /* 430 */ 25, 193, 101, 193, 193, 231, 114, 25, 116, 117,
+ /* 440 */ 118, 113, 304, 121, 193, 204, 59, 119, 120, 121,
+ /* 450 */ 122, 123, 124, 125, 216, 217, 193, 216, 217, 131,
+ /* 460 */ 138, 139, 230, 102, 103, 104, 105, 106, 107, 108,
+ /* 470 */ 109, 110, 111, 112, 113, 153, 154, 155, 156, 157,
+ /* 480 */ 239, 240, 116, 117, 118, 76, 193, 23, 19, 25,
+ /* 490 */ 22, 253, 23, 252, 253, 108, 87, 204, 89, 261,
+ /* 500 */ 198, 92, 261, 116, 117, 118, 193, 306, 307, 216,
+ /* 510 */ 217, 150, 43, 44, 45, 46, 47, 48, 49, 50,
+ /* 520 */ 51, 52, 53, 54, 55, 56, 57, 59, 193, 216,
+ /* 530 */ 217, 19, 239, 240, 283, 23, 106, 107, 108, 109,
+ /* 540 */ 110, 111, 112, 113, 73, 252, 253, 142, 308, 309,
+ /* 550 */ 138, 139, 81, 313, 145, 43, 44, 45, 46, 47,
+ /* 560 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+ /* 570 */ 307, 102, 103, 104, 105, 106, 107, 108, 109, 110,
+ /* 580 */ 111, 112, 113, 281, 116, 117, 118, 285, 23, 193,
+ /* 590 */ 25, 119, 59, 193, 122, 123, 124, 59, 127, 203,
+ /* 600 */ 59, 205, 19, 268, 132, 25, 23, 22, 193, 138,
+ /* 610 */ 139, 249, 204, 251, 102, 103, 104, 105, 106, 107,
+ /* 620 */ 108, 109, 110, 111, 112, 113, 43, 44, 45, 46,
+ /* 630 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ /* 640 */ 57, 19, 22, 23, 59, 23, 25, 239, 240, 116,
+ /* 650 */ 117, 118, 193, 11, 116, 117, 118, 116, 117, 118,
+ /* 660 */ 252, 269, 22, 193, 15, 43, 44, 45, 46, 47,
+ /* 670 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+ /* 680 */ 273, 143, 193, 118, 143, 102, 103, 104, 105, 106,
+ /* 690 */ 107, 108, 109, 110, 111, 112, 113, 76, 118, 59,
+ /* 700 */ 241, 116, 117, 118, 304, 216, 217, 292, 143, 60,
+ /* 710 */ 89, 241, 19, 92, 193, 193, 23, 22, 311, 312,
+ /* 720 */ 231, 101, 22, 143, 102, 103, 104, 105, 106, 107,
+ /* 730 */ 108, 109, 110, 111, 112, 113, 43, 44, 45, 46,
+ /* 740 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ /* 750 */ 57, 19, 193, 193, 59, 23, 116, 117, 118, 59,
+ /* 760 */ 201, 21, 241, 304, 22, 206, 127, 128, 129, 193,
+ /* 770 */ 128, 129, 235, 236, 304, 43, 44, 45, 46, 47,
+ /* 780 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+ /* 790 */ 22, 193, 216, 217, 193, 102, 103, 104, 105, 106,
+ /* 800 */ 107, 108, 109, 110, 111, 112, 113, 231, 193, 193,
+ /* 810 */ 193, 116, 117, 118, 216, 217, 116, 117, 118, 226,
+ /* 820 */ 80, 193, 19, 235, 236, 304, 23, 211, 212, 231,
+ /* 830 */ 204, 216, 217, 205, 102, 103, 104, 105, 106, 107,
+ /* 840 */ 108, 109, 110, 111, 112, 113, 43, 44, 45, 46,
+ /* 850 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ /* 860 */ 57, 19, 193, 123, 76, 239, 240, 193, 253, 239,
+ /* 870 */ 240, 239, 240, 193, 106, 107, 193, 89, 252, 193,
+ /* 880 */ 92, 59, 252, 141, 252, 43, 44, 45, 46, 47,
+ /* 890 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+ /* 900 */ 284, 161, 216, 217, 193, 102, 103, 104, 105, 106,
+ /* 910 */ 107, 108, 109, 110, 111, 112, 113, 231, 193, 16,
+ /* 920 */ 187, 188, 189, 190, 7, 8, 9, 309, 195, 25,
+ /* 930 */ 197, 313, 19, 127, 128, 129, 262, 204, 22, 117,
+ /* 940 */ 24, 216, 217, 263, 102, 103, 104, 105, 106, 107,
+ /* 950 */ 108, 109, 110, 111, 112, 113, 43, 44, 45, 46,
+ /* 960 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ /* 970 */ 57, 193, 239, 240, 193, 59, 19, 188, 253, 190,
+ /* 980 */ 77, 226, 79, 193, 195, 252, 197, 193, 19, 301,
+ /* 990 */ 302, 193, 193, 204, 216, 217, 226, 216, 217, 266,
+ /* 1000 */ 204, 159, 45, 46, 47, 48, 49, 50, 51, 52,
+ /* 1010 */ 53, 54, 55, 56, 57, 102, 103, 104, 105, 106,
+ /* 1020 */ 107, 108, 109, 110, 111, 112, 113, 12, 239, 240,
+ /* 1030 */ 232, 298, 238, 117, 253, 239, 240, 238, 259, 260,
+ /* 1040 */ 193, 252, 27, 31, 193, 193, 142, 204, 252, 193,
+ /* 1050 */ 193, 39, 262, 193, 100, 266, 278, 42, 204, 102,
+ /* 1060 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
+ /* 1070 */ 113, 117, 159, 216, 217, 121, 216, 217, 63, 193,
+ /* 1080 */ 193, 193, 239, 240, 115, 116, 193, 298, 73, 238,
+ /* 1090 */ 238, 231, 19, 239, 240, 252, 22, 24, 211, 212,
+ /* 1100 */ 24, 193, 216, 217, 216, 217, 252, 153, 154, 155,
+ /* 1110 */ 253, 16, 19, 144, 213, 268, 43, 44, 45, 46,
+ /* 1120 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ /* 1130 */ 57, 238, 19, 59, 193, 59, 43, 44, 45, 46,
+ /* 1140 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ /* 1150 */ 57, 22, 23, 193, 25, 193, 43, 44, 45, 46,
+ /* 1160 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ /* 1170 */ 57, 284, 77, 193, 79, 102, 103, 104, 105, 106,
+ /* 1180 */ 107, 108, 109, 110, 111, 112, 113, 286, 193, 193,
+ /* 1190 */ 193, 117, 291, 117, 232, 102, 103, 104, 105, 106,
+ /* 1200 */ 107, 108, 109, 110, 111, 112, 113, 204, 22, 23,
+ /* 1210 */ 66, 25, 216, 217, 35, 102, 103, 104, 105, 106,
+ /* 1220 */ 107, 108, 109, 110, 111, 112, 113, 193, 268, 85,
+ /* 1230 */ 101, 193, 309, 309, 240, 19, 313, 313, 94, 208,
+ /* 1240 */ 209, 193, 239, 240, 193, 66, 252, 19, 268, 244,
+ /* 1250 */ 216, 217, 193, 74, 213, 252, 161, 19, 263, 254,
+ /* 1260 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
+ /* 1270 */ 54, 55, 56, 57, 193, 216, 217, 5, 59, 193,
+ /* 1280 */ 19, 244, 10, 11, 12, 13, 14, 101, 309, 17,
+ /* 1290 */ 146, 254, 313, 193, 193, 76, 115, 216, 217, 309,
+ /* 1300 */ 12, 263, 30, 313, 32, 46, 87, 46, 89, 130,
+ /* 1310 */ 193, 92, 40, 22, 263, 27, 216, 217, 102, 103,
+ /* 1320 */ 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
+ /* 1330 */ 42, 150, 291, 216, 217, 116, 117, 118, 19, 20,
+ /* 1340 */ 193, 22, 70, 260, 116, 193, 24, 264, 193, 263,
+ /* 1350 */ 78, 63, 61, 81, 116, 36, 193, 260, 193, 29,
+ /* 1360 */ 193, 264, 193, 33, 145, 193, 59, 48, 216, 217,
+ /* 1370 */ 98, 216, 217, 193, 115, 193, 115, 193, 59, 216,
+ /* 1380 */ 217, 216, 217, 216, 217, 216, 217, 255, 216, 217,
+ /* 1390 */ 71, 193, 131, 193, 25, 65, 216, 217, 216, 217,
+ /* 1400 */ 216, 217, 208, 209, 85, 133, 193, 100, 193, 90,
+ /* 1410 */ 138, 139, 138, 139, 216, 217, 216, 217, 193, 100,
+ /* 1420 */ 193, 108, 135, 116, 117, 106, 107, 140, 121, 216,
+ /* 1430 */ 217, 216, 217, 114, 162, 116, 117, 118, 299, 300,
+ /* 1440 */ 121, 216, 217, 216, 217, 193, 244, 193, 135, 244,
+ /* 1450 */ 193, 256, 257, 140, 244, 193, 254, 193, 193, 254,
+ /* 1460 */ 153, 154, 155, 141, 254, 149, 150, 258, 216, 217,
+ /* 1470 */ 216, 217, 153, 154, 155, 156, 157, 0, 1, 2,
+ /* 1480 */ 216, 217, 5, 115, 158, 193, 160, 10, 11, 12,
+ /* 1490 */ 13, 14, 193, 59, 17, 126, 193, 19, 20, 129,
+ /* 1500 */ 22, 193, 22, 22, 24, 193, 23, 30, 25, 32,
+ /* 1510 */ 19, 20, 144, 22, 36, 216, 217, 40, 193, 216,
+ /* 1520 */ 217, 193, 152, 129, 216, 217, 193, 36, 216, 217,
+ /* 1530 */ 193, 99, 193, 193, 53, 193, 193, 59, 23, 193,
+ /* 1540 */ 25, 216, 217, 193, 216, 217, 152, 70, 59, 71,
+ /* 1550 */ 59, 117, 193, 216, 217, 78, 216, 217, 81, 216,
+ /* 1560 */ 217, 318, 71, 85, 193, 133, 193, 193, 90, 23,
+ /* 1570 */ 23, 25, 25, 120, 121, 98, 85, 193, 100, 193,
+ /* 1580 */ 23, 90, 25, 121, 106, 107, 19, 216, 217, 216,
+ /* 1590 */ 217, 100, 114, 131, 116, 117, 118, 106, 107, 121,
+ /* 1600 */ 216, 217, 216, 217, 193, 114, 117, 116, 117, 118,
+ /* 1610 */ 133, 193, 121, 193, 193, 138, 139, 193, 23, 193,
+ /* 1620 */ 25, 23, 23, 25, 25, 7, 8, 216, 217, 193,
+ /* 1630 */ 193, 153, 154, 155, 156, 157, 216, 217, 193, 162,
+ /* 1640 */ 216, 217, 216, 217, 153, 154, 155, 156, 157, 1,
+ /* 1650 */ 2, 193, 193, 5, 19, 20, 59, 22, 10, 11,
+ /* 1660 */ 12, 13, 14, 193, 97, 17, 193, 23, 193, 25,
+ /* 1670 */ 288, 36, 193, 242, 216, 217, 236, 23, 30, 25,
+ /* 1680 */ 32, 19, 20, 23, 22, 25, 216, 217, 40, 216,
+ /* 1690 */ 217, 216, 217, 193, 59, 216, 217, 193, 36, 83,
+ /* 1700 */ 84, 153, 153, 155, 155, 23, 71, 25, 23, 193,
+ /* 1710 */ 25, 193, 193, 193, 117, 193, 193, 193, 70, 193,
+ /* 1720 */ 193, 59, 193, 255, 255, 287, 78, 255, 243, 81,
+ /* 1730 */ 191, 255, 297, 71, 271, 100, 293, 245, 267, 214,
+ /* 1740 */ 246, 106, 107, 108, 246, 271, 98, 245, 293, 114,
+ /* 1750 */ 220, 116, 117, 118, 267, 271, 121, 271, 225, 219,
+ /* 1760 */ 229, 219, 100, 219, 259, 259, 259, 259, 106, 107,
+ /* 1770 */ 249, 196, 60, 280, 141, 243, 114, 249, 116, 117,
+ /* 1780 */ 118, 133, 245, 121, 200, 297, 138, 139, 153, 154,
+ /* 1790 */ 155, 156, 157, 297, 200, 38, 19, 20, 151, 22,
+ /* 1800 */ 200, 150, 140, 294, 294, 22, 272, 148, 250, 145,
+ /* 1810 */ 162, 270, 249, 36, 43, 153, 154, 155, 156, 157,
+ /* 1820 */ 234, 283, 250, 249, 18, 237, 237, 237, 237, 200,
+ /* 1830 */ 18, 199, 149, 246, 272, 234, 59, 272, 246, 270,
+ /* 1840 */ 234, 200, 246, 290, 199, 158, 62, 22, 71, 246,
+ /* 1850 */ 289, 221, 200, 200, 199, 199, 19, 20, 200, 22,
+ /* 1860 */ 199, 221, 115, 64, 218, 227, 22, 218, 218, 126,
+ /* 1870 */ 227, 165, 312, 36, 24, 305, 113, 100, 200, 91,
+ /* 1880 */ 82, 224, 22, 106, 107, 218, 221, 224, 220, 218,
+ /* 1890 */ 218, 114, 218, 116, 117, 118, 59, 282, 121, 282,
+ /* 1900 */ 221, 265, 317, 277, 265, 200, 158, 279, 71, 147,
+ /* 1910 */ 317, 146, 25, 202, 13, 194, 250, 140, 249, 194,
+ /* 1920 */ 250, 248, 247, 246, 6, 192, 192, 192, 303, 207,
+ /* 1930 */ 153, 154, 155, 156, 157, 222, 213, 100, 207, 213,
+ /* 1940 */ 303, 213, 300, 106, 107, 213, 222, 207, 4, 3,
+ /* 1950 */ 214, 114, 214, 116, 117, 118, 22, 213, 121, 163,
+ /* 1960 */ 15, 23, 23, 16, 151, 139, 130, 25, 144, 142,
+ /* 1970 */ 20, 16, 24, 1, 142, 130, 130, 61, 37, 151,
+ /* 1980 */ 53, 53, 53, 53, 130, 116, 34, 1, 141, 5,
+ /* 1990 */ 153, 154, 155, 156, 157, 22, 115, 75, 41, 161,
+ /* 2000 */ 68, 25, 141, 68, 115, 24, 131, 20, 19, 125,
+ /* 2010 */ 22, 96, 22, 22, 37, 23, 67, 22, 67, 59,
+ /* 2020 */ 24, 28, 22, 67, 23, 149, 22, 25, 23, 23,
+ /* 2030 */ 23, 23, 22, 97, 141, 23, 23, 116, 22, 143,
+ /* 2040 */ 25, 88, 75, 34, 86, 34, 75, 44, 34, 23,
+ /* 2050 */ 22, 34, 34, 34, 93, 24, 34, 25, 25, 142,
+ /* 2060 */ 23, 142, 23, 23, 23, 23, 11, 23, 25, 22,
+ /* 2070 */ 22, 22, 135, 23, 23, 22, 22, 25, 15, 23,
+ /* 2080 */ 1, 141, 25, 1, 141, 319, 319, 319, 319, 319,
+ /* 2090 */ 319, 319, 319, 319, 319, 141, 319, 319, 319, 319,
+ /* 2100 */ 141, 319, 319, 319, 319, 319, 319, 319, 319, 319,
+ /* 2110 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319,
+ /* 2120 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319,
+ /* 2130 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319,
+ /* 2140 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319,
+ /* 2150 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319,
+ /* 2160 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319,
+ /* 2170 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319,
+ /* 2180 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319,
+ /* 2190 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319,
+ /* 2200 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319,
+ /* 2210 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319,
+ /* 2220 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319,
+ /* 2230 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319,
+ /* 2240 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319,
+ /* 2250 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319,
+ /* 2260 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319,
+ /* 2270 */ 319, 319, 319, 319, 319, 319, 319, 319, 319, 319,
+ /* 2280 */ 319, 319, 319, 319, 319, 319,
};
-#define YY_SHIFT_COUNT (556)
+#define YY_SHIFT_COUNT (579)
#define YY_SHIFT_MIN (0)
-#define YY_SHIFT_MAX (1954)
+#define YY_SHIFT_MAX (2082)
static const unsigned short int yy_shift_ofst[] = {
- /* 0 */ 1448, 1277, 1668, 1072, 1072, 340, 1122, 1225, 1332, 1481,
- /* 10 */ 1481, 1481, 335, 0, 0, 180, 897, 1481, 1481, 1481,
- /* 20 */ 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481,
- /* 30 */ 930, 930, 1020, 1020, 290, 1, 340, 340, 340, 340,
- /* 40 */ 340, 340, 40, 110, 219, 288, 327, 396, 435, 504,
- /* 50 */ 543, 612, 651, 720, 877, 897, 897, 897, 897, 897,
- /* 60 */ 897, 897, 897, 897, 897, 897, 897, 897, 897, 897,
- /* 70 */ 897, 897, 897, 917, 897, 1019, 763, 763, 1451, 1481,
- /* 80 */ 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481,
- /* 90 */ 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481,
- /* 100 */ 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481,
- /* 110 */ 1481, 1481, 1553, 1481, 1481, 1481, 1481, 1481, 1481, 1481,
- /* 120 */ 1481, 1481, 1481, 1481, 1481, 1481, 147, 258, 258, 258,
- /* 130 */ 258, 258, 79, 65, 84, 449, 19, 786, 449, 636,
- /* 140 */ 636, 449, 880, 880, 880, 880, 113, 142, 142, 472,
- /* 150 */ 150, 1974, 1974, 399, 399, 399, 93, 237, 341, 237,
- /* 160 */ 237, 1074, 1074, 437, 350, 704, 1080, 449, 449, 449,
- /* 170 */ 449, 449, 449, 449, 449, 449, 449, 449, 449, 449,
- /* 180 */ 449, 449, 449, 449, 449, 449, 449, 449, 818, 818,
- /* 190 */ 449, 1088, 217, 217, 734, 734, 1124, 1126, 1974, 1974,
- /* 200 */ 1974, 739, 840, 840, 453, 454, 511, 187, 563, 570,
- /* 210 */ 898, 669, 449, 449, 449, 449, 449, 449, 449, 449,
- /* 220 */ 449, 670, 449, 449, 449, 449, 449, 449, 449, 449,
- /* 230 */ 449, 449, 449, 449, 674, 674, 674, 449, 449, 449,
- /* 240 */ 449, 1034, 449, 449, 449, 972, 1107, 449, 449, 1193,
- /* 250 */ 449, 449, 449, 449, 449, 449, 449, 449, 260, 177,
- /* 260 */ 489, 1241, 1241, 1241, 1241, 1192, 489, 489, 952, 1197,
- /* 270 */ 625, 1235, 1131, 181, 181, 1086, 1139, 1131, 1086, 1187,
- /* 280 */ 1319, 1237, 1318, 1318, 1318, 181, 1299, 1299, 1109, 1336,
- /* 290 */ 549, 1376, 1610, 1535, 1535, 1639, 1639, 1535, 1539, 1578,
- /* 300 */ 1670, 1547, 1551, 1549, 1658, 1547, 1551, 1549, 1694, 1694,
- /* 310 */ 1694, 1694, 1535, 1702, 1549, 1549, 1578, 1670, 1658, 1549,
- /* 320 */ 1658, 1549, 1535, 1702, 1575, 1669, 1535, 1702, 1712, 1535,
- /* 330 */ 1702, 1535, 1702, 1712, 1631, 1631, 1631, 1686, 1730, 1730,
- /* 340 */ 1712, 1631, 1629, 1631, 1686, 1631, 1631, 1594, 1712, 1646,
- /* 350 */ 1646, 1712, 1617, 1648, 1617, 1648, 1617, 1648, 1617, 1648,
- /* 360 */ 1535, 1693, 1693, 1705, 1705, 1547, 1551, 1766, 1535, 1635,
- /* 370 */ 1547, 1650, 1649, 1549, 1771, 1772, 1788, 1788, 1801, 1801,
- /* 380 */ 1801, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974, 1974,
- /* 390 */ 1974, 1974, 1974, 1974, 1974, 1974, 308, 835, 954, 1232,
- /* 400 */ 879, 715, 728, 1373, 864, 1329, 1253, 1409, 297, 1431,
- /* 410 */ 1489, 1497, 1520, 1521, 1525, 1362, 1309, 1491, 1217, 1420,
- /* 420 */ 1429, 1536, 1380, 1538, 1293, 1354, 1548, 1585, 1434, 1342,
- /* 430 */ 1821, 1823, 1811, 1674, 1820, 1738, 1822, 1814, 1816, 1703,
- /* 440 */ 1695, 1713, 1818, 1704, 1825, 1706, 1830, 1846, 1709, 1701,
- /* 450 */ 1723, 1791, 1817, 1707, 1800, 1803, 1804, 1805, 1731, 1746,
- /* 460 */ 1827, 1724, 1861, 1859, 1845, 1755, 1711, 1802, 1847, 1806,
- /* 470 */ 1796, 1831, 1736, 1763, 1853, 1858, 1860, 1751, 1758, 1862,
- /* 480 */ 1815, 1863, 1864, 1865, 1867, 1824, 1828, 1866, 1787, 1868,
- /* 490 */ 1870, 1826, 1857, 1872, 1750, 1876, 1877, 1878, 1879, 1873,
- /* 500 */ 1880, 1882, 1881, 1883, 1885, 1884, 1770, 1887, 1888, 1798,
- /* 510 */ 1886, 1891, 1773, 1889, 1890, 1892, 1893, 1894, 1829, 1841,
- /* 520 */ 1832, 1875, 1848, 1836, 1896, 1898, 1900, 1901, 1905, 1906,
- /* 530 */ 1899, 1911, 1889, 1912, 1913, 1914, 1915, 1916, 1917, 1919,
- /* 540 */ 1928, 1921, 1922, 1923, 1924, 1926, 1927, 1925, 1812, 1813,
- /* 550 */ 1819, 1833, 1834, 1930, 1935, 1953, 1954,
+ /* 0 */ 1648, 1477, 1272, 322, 322, 1, 1319, 1478, 1491, 1837,
+ /* 10 */ 1837, 1837, 471, 0, 0, 214, 1093, 1837, 1837, 1837,
+ /* 20 */ 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837,
+ /* 30 */ 271, 271, 1219, 1219, 216, 88, 1, 1, 1, 1,
+ /* 40 */ 1, 40, 111, 258, 361, 469, 512, 583, 622, 693,
+ /* 50 */ 732, 803, 842, 913, 1073, 1093, 1093, 1093, 1093, 1093,
+ /* 60 */ 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093,
+ /* 70 */ 1093, 1093, 1093, 1113, 1093, 1216, 957, 957, 1635, 1662,
+ /* 80 */ 1777, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837,
+ /* 90 */ 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837,
+ /* 100 */ 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837,
+ /* 110 */ 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837,
+ /* 120 */ 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837, 1837,
+ /* 130 */ 137, 181, 181, 181, 181, 181, 181, 181, 94, 430,
+ /* 140 */ 66, 65, 112, 366, 533, 533, 740, 1261, 533, 533,
+ /* 150 */ 79, 79, 533, 412, 412, 412, 77, 412, 123, 113,
+ /* 160 */ 113, 22, 22, 2101, 2101, 328, 328, 328, 239, 468,
+ /* 170 */ 468, 468, 468, 1015, 1015, 409, 366, 1129, 1186, 533,
+ /* 180 */ 533, 533, 533, 533, 533, 533, 533, 533, 533, 533,
+ /* 190 */ 533, 533, 533, 533, 533, 533, 533, 533, 533, 969,
+ /* 200 */ 621, 621, 533, 642, 788, 788, 1228, 1228, 822, 822,
+ /* 210 */ 67, 1274, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 1307,
+ /* 220 */ 954, 954, 585, 472, 640, 387, 695, 538, 541, 700,
+ /* 230 */ 533, 533, 533, 533, 533, 533, 533, 533, 533, 533,
+ /* 240 */ 222, 533, 533, 533, 533, 533, 533, 533, 533, 533,
+ /* 250 */ 533, 533, 533, 1179, 1179, 1179, 533, 533, 533, 565,
+ /* 260 */ 533, 533, 533, 916, 1144, 533, 533, 1288, 533, 533,
+ /* 270 */ 533, 533, 533, 533, 533, 533, 639, 1330, 209, 1076,
+ /* 280 */ 1076, 1076, 1076, 580, 209, 209, 1313, 768, 917, 649,
+ /* 290 */ 1181, 1316, 405, 1316, 1238, 249, 1181, 1181, 249, 1181,
+ /* 300 */ 405, 1238, 1369, 464, 1259, 1012, 1012, 1012, 1368, 1368,
+ /* 310 */ 1368, 1368, 184, 184, 1326, 904, 1287, 1480, 1712, 1712,
+ /* 320 */ 1633, 1633, 1757, 1757, 1633, 1647, 1651, 1783, 1659, 1664,
+ /* 330 */ 1771, 1659, 1664, 1806, 1806, 1806, 1806, 1633, 1812, 1683,
+ /* 340 */ 1651, 1651, 1683, 1783, 1771, 1683, 1771, 1683, 1633, 1812,
+ /* 350 */ 1687, 1784, 1633, 1812, 1825, 1633, 1812, 1633, 1812, 1825,
+ /* 360 */ 1747, 1747, 1747, 1799, 1844, 1844, 1825, 1747, 1743, 1747,
+ /* 370 */ 1799, 1747, 1747, 1706, 1850, 1763, 1763, 1825, 1633, 1788,
+ /* 380 */ 1788, 1798, 1798, 1659, 1664, 1860, 1633, 1748, 1659, 1762,
+ /* 390 */ 1765, 1683, 1887, 1901, 1901, 1918, 1918, 1918, 2101, 2101,
+ /* 400 */ 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101, 2101,
+ /* 410 */ 2101, 2101, 2101, 207, 1095, 331, 620, 903, 806, 1074,
+ /* 420 */ 1483, 1432, 1481, 1322, 1370, 1394, 1515, 1291, 1546, 1547,
+ /* 430 */ 1557, 1595, 1598, 1599, 1434, 1453, 1618, 1462, 1567, 1489,
+ /* 440 */ 1644, 1654, 1616, 1660, 1548, 1549, 1682, 1685, 1597, 742,
+ /* 450 */ 1944, 1946, 1934, 1796, 1945, 1947, 1938, 1939, 1826, 1813,
+ /* 460 */ 1836, 1942, 1942, 1948, 1827, 1950, 1824, 1955, 1972, 1832,
+ /* 470 */ 1845, 1942, 1846, 1916, 1941, 1942, 1828, 1927, 1928, 1929,
+ /* 480 */ 1930, 1854, 1869, 1952, 1847, 1986, 1984, 1973, 1881, 1838,
+ /* 490 */ 1932, 1976, 1935, 1922, 1957, 1861, 1889, 1981, 1987, 1989,
+ /* 500 */ 1875, 1884, 1988, 1949, 1990, 1991, 1992, 1995, 1951, 1960,
+ /* 510 */ 1996, 1915, 1993, 2000, 1956, 1977, 2001, 1876, 2004, 2005,
+ /* 520 */ 2006, 2007, 2002, 2008, 2010, 1936, 1893, 2012, 2013, 1921,
+ /* 530 */ 2009, 2016, 1896, 2015, 2011, 2014, 2017, 2018, 1953, 1967,
+ /* 540 */ 1958, 2003, 1971, 1961, 2019, 2026, 2028, 2031, 2032, 2033,
+ /* 550 */ 2022, 1917, 1919, 2037, 2015, 2039, 2040, 2041, 2042, 2043,
+ /* 560 */ 2044, 2047, 2055, 2048, 2049, 2050, 2051, 2053, 2054, 2052,
+ /* 570 */ 1937, 1940, 1943, 1954, 1959, 2057, 2056, 2063, 2079, 2082,
};
-#define YY_REDUCE_COUNT (395)
-#define YY_REDUCE_MIN (-262)
-#define YY_REDUCE_MAX (1627)
+#define YY_REDUCE_COUNT (412)
+#define YY_REDUCE_MIN (-271)
+#define YY_REDUCE_MAX (1744)
static const short yy_reduce_ofst[] = {
- /* 0 */ 490, -122, 545, 645, 650, -120, -189, -187, -184, -182,
- /* 10 */ -178, -176, 45, 30, 200, -251, -134, 390, 392, 521,
- /* 20 */ 523, 213, 692, 821, 284, 589, 872, 666, 671, 866,
- /* 30 */ 71, 111, 273, 389, 686, 815, 904, 932, 948, 955,
- /* 40 */ 964, 969, -259, -259, -259, -259, -259, -259, -259, -259,
- /* 50 */ -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
- /* 60 */ -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
- /* 70 */ -259, -259, -259, -259, -259, -259, -259, -259, 428, 430,
- /* 80 */ 899, 985, 1021, 1028, 1057, 1069, 1081, 1108, 1110, 1115,
- /* 90 */ 1117, 1123, 1149, 1154, 1159, 1170, 1174, 1178, 1183, 1194,
- /* 100 */ 1198, 1204, 1208, 1212, 1218, 1222, 1229, 1278, 1280, 1283,
- /* 110 */ 1285, 1313, 1316, 1320, 1322, 1325, 1327, 1330, 1366, 1371,
- /* 120 */ 1379, 1387, 1417, 1425, 1430, 1432, -259, -259, -259, -259,
- /* 130 */ -259, -259, -259, -259, -259, 557, 974, -214, -174, -9,
- /* 140 */ 431, -124, 806, 925, 806, 925, 251, 928, 940, -259,
- /* 150 */ -259, -259, -259, -198, -198, -198, 127, -186, -168, 212,
- /* 160 */ 646, 617, 799, -262, 555, 220, 220, 491, 605, 1040,
- /* 170 */ 1060, 699, -11, 600, 848, 862, 345, -129, 724, -91,
- /* 180 */ 158, 749, 716, 900, 304, 822, 929, 926, 499, 793,
- /* 190 */ 322, 892, 813, 845, 958, 1056, 751, 905, 1133, 1062,
- /* 200 */ 803, -210, -185, -179, -148, -167, -89, 121, 274, 281,
- /* 210 */ 320, 336, 439, 663, 711, 957, 965, 1064, 1068, 1112,
- /* 220 */ 1116, -196, 1127, 1134, 1180, 1184, 1195, 1199, 1203, 1215,
- /* 230 */ 1223, 1250, 1267, 1286, 205, 422, 638, 1324, 1341, 1364,
- /* 240 */ 1365, 1213, 1392, 1399, 1403, 869, 1260, 1405, 1421, 1276,
- /* 250 */ 1424, 121, 1426, 1427, 1428, 1433, 1436, 1437, 1227, 1338,
- /* 260 */ 1284, 1359, 1370, 1377, 1388, 1213, 1284, 1284, 1385, 1438,
- /* 270 */ 1443, 1349, 1400, 1391, 1394, 1360, 1408, 1410, 1367, 1439,
- /* 280 */ 1440, 1435, 1442, 1446, 1447, 1397, 1413, 1418, 1390, 1444,
- /* 290 */ 1445, 1474, 1381, 1479, 1480, 1401, 1402, 1490, 1414, 1449,
- /* 300 */ 1452, 1450, 1453, 1458, 1473, 1464, 1466, 1470, 1483, 1485,
- /* 310 */ 1486, 1487, 1517, 1526, 1482, 1484, 1457, 1460, 1498, 1488,
- /* 320 */ 1499, 1492, 1530, 1537, 1454, 1459, 1540, 1544, 1519, 1546,
- /* 330 */ 1545, 1552, 1550, 1527, 1534, 1541, 1542, 1529, 1543, 1554,
- /* 340 */ 1555, 1556, 1557, 1561, 1558, 1562, 1563, 1455, 1565, 1493,
- /* 350 */ 1495, 1566, 1504, 1508, 1510, 1509, 1511, 1522, 1523, 1528,
- /* 360 */ 1582, 1477, 1478, 1531, 1532, 1564, 1559, 1524, 1593, 1560,
- /* 370 */ 1567, 1568, 1571, 1569, 1598, 1602, 1612, 1616, 1620, 1626,
- /* 380 */ 1627, 1533, 1570, 1572, 1614, 1609, 1611, 1613, 1615, 1618,
- /* 390 */ 1601, 1605, 1619, 1621, 1623, 1622,
+ /* 0 */ -125, 733, 789, 241, 293, -123, -193, -191, -183, -187,
+ /* 10 */ 166, 238, 133, -207, -199, -267, -176, -6, 204, 489,
+ /* 20 */ 576, -175, 598, 686, 615, 725, 860, 778, 781, 857,
+ /* 30 */ 616, 887, 87, 240, -192, 408, 626, 796, 843, 854,
+ /* 40 */ 1003, -271, -271, -271, -271, -271, -271, -271, -271, -271,
+ /* 50 */ -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
+ /* 60 */ -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
+ /* 70 */ -271, -271, -271, -271, -271, -271, -271, -271, 80, 83,
+ /* 80 */ 313, 886, 888, 996, 1034, 1059, 1081, 1100, 1117, 1152,
+ /* 90 */ 1155, 1163, 1165, 1167, 1169, 1172, 1180, 1182, 1184, 1198,
+ /* 100 */ 1200, 1213, 1215, 1225, 1227, 1252, 1254, 1264, 1299, 1303,
+ /* 110 */ 1308, 1312, 1325, 1328, 1337, 1340, 1343, 1371, 1373, 1384,
+ /* 120 */ 1386, 1411, 1420, 1424, 1426, 1458, 1470, 1473, 1475, 1479,
+ /* 130 */ -271, -271, -271, -271, -271, -271, -271, -271, -271, -271,
+ /* 140 */ -271, 138, 459, 396, -158, 470, 302, -212, 521, 201,
+ /* 150 */ -195, -92, 559, 630, 632, 630, -271, 632, 901, 63,
+ /* 160 */ 407, -271, -271, -271, -271, 161, 161, 161, 251, 335,
+ /* 170 */ 847, 960, 980, 537, 588, 618, 628, 688, 688, -166,
+ /* 180 */ -161, 674, 790, 794, 799, 851, 852, -122, 680, -120,
+ /* 190 */ 995, 1038, 415, 1051, 893, 798, 962, 400, 1086, 779,
+ /* 200 */ 923, 924, 263, 1041, 979, 990, 1083, 1097, 1031, 1194,
+ /* 210 */ 362, 994, 1139, 1005, 1037, 1202, 1205, 1195, 1210, -194,
+ /* 220 */ 56, 185, -135, 232, 522, 560, 601, 617, 669, 683,
+ /* 230 */ 711, 856, 908, 941, 1048, 1101, 1147, 1257, 1262, 1265,
+ /* 240 */ 392, 1292, 1333, 1339, 1342, 1346, 1350, 1359, 1374, 1418,
+ /* 250 */ 1421, 1436, 1437, 593, 755, 770, 997, 1445, 1459, 1209,
+ /* 260 */ 1500, 1504, 1516, 1132, 1243, 1518, 1519, 1440, 1520, 560,
+ /* 270 */ 1522, 1523, 1524, 1526, 1527, 1529, 1382, 1438, 1431, 1468,
+ /* 280 */ 1469, 1472, 1476, 1209, 1431, 1431, 1485, 1525, 1539, 1435,
+ /* 290 */ 1463, 1471, 1492, 1487, 1443, 1494, 1474, 1484, 1498, 1486,
+ /* 300 */ 1502, 1455, 1530, 1531, 1533, 1540, 1542, 1544, 1505, 1506,
+ /* 310 */ 1507, 1508, 1521, 1528, 1493, 1537, 1532, 1575, 1488, 1496,
+ /* 320 */ 1584, 1594, 1509, 1510, 1600, 1538, 1534, 1541, 1558, 1563,
+ /* 330 */ 1586, 1572, 1574, 1588, 1589, 1590, 1591, 1629, 1632, 1587,
+ /* 340 */ 1562, 1565, 1592, 1569, 1601, 1596, 1606, 1603, 1641, 1645,
+ /* 350 */ 1553, 1561, 1652, 1655, 1630, 1653, 1656, 1658, 1661, 1640,
+ /* 360 */ 1646, 1649, 1650, 1638, 1657, 1663, 1665, 1667, 1668, 1671,
+ /* 370 */ 1643, 1672, 1674, 1560, 1570, 1615, 1617, 1679, 1678, 1585,
+ /* 380 */ 1593, 1636, 1639, 1666, 1669, 1626, 1705, 1628, 1670, 1673,
+ /* 390 */ 1675, 1677, 1711, 1721, 1725, 1733, 1734, 1735, 1625, 1637,
+ /* 400 */ 1642, 1722, 1723, 1726, 1728, 1732, 1731, 1713, 1724, 1736,
+ /* 410 */ 1738, 1744, 1740,
};
static const YYACTIONTYPE yy_default[] = {
- /* 0 */ 1579, 1579, 1579, 1415, 1192, 1301, 1192, 1192, 1192, 1415,
- /* 10 */ 1415, 1415, 1192, 1331, 1331, 1468, 1223, 1192, 1192, 1192,
- /* 20 */ 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1414, 1192, 1192,
- /* 30 */ 1192, 1192, 1498, 1498, 1192, 1192, 1192, 1192, 1192, 1192,
- /* 40 */ 1192, 1192, 1192, 1340, 1192, 1192, 1192, 1192, 1192, 1192,
- /* 50 */ 1416, 1417, 1192, 1192, 1192, 1467, 1469, 1432, 1350, 1349,
- /* 60 */ 1348, 1347, 1450, 1318, 1345, 1338, 1342, 1410, 1411, 1409,
- /* 70 */ 1413, 1417, 1416, 1192, 1341, 1381, 1395, 1380, 1192, 1192,
- /* 80 */ 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192,
- /* 90 */ 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192,
- /* 100 */ 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192,
- /* 110 */ 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192,
- /* 120 */ 1192, 1192, 1192, 1192, 1192, 1192, 1389, 1394, 1400, 1393,
- /* 130 */ 1390, 1383, 1382, 1384, 1385, 1192, 1213, 1265, 1192, 1192,
- /* 140 */ 1192, 1192, 1486, 1485, 1192, 1192, 1223, 1375, 1374, 1386,
- /* 150 */ 1387, 1397, 1396, 1475, 1533, 1532, 1433, 1192, 1192, 1192,
- /* 160 */ 1192, 1192, 1192, 1498, 1192, 1192, 1192, 1192, 1192, 1192,
- /* 170 */ 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192,
- /* 180 */ 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1498, 1498,
- /* 190 */ 1192, 1223, 1498, 1498, 1219, 1219, 1325, 1192, 1481, 1301,
- /* 200 */ 1292, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192,
- /* 210 */ 1192, 1192, 1192, 1192, 1192, 1472, 1470, 1192, 1192, 1192,
- /* 220 */ 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192,
- /* 230 */ 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192,
- /* 240 */ 1192, 1192, 1192, 1192, 1192, 1297, 1192, 1192, 1192, 1192,
- /* 250 */ 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1527, 1192, 1445,
- /* 260 */ 1279, 1297, 1297, 1297, 1297, 1299, 1280, 1278, 1291, 1224,
- /* 270 */ 1199, 1571, 1298, 1320, 1320, 1568, 1344, 1298, 1568, 1240,
- /* 280 */ 1549, 1235, 1331, 1331, 1331, 1320, 1325, 1325, 1412, 1298,
- /* 290 */ 1291, 1192, 1571, 1306, 1306, 1570, 1570, 1306, 1433, 1353,
- /* 300 */ 1359, 1339, 1325, 1344, 1268, 1339, 1325, 1344, 1274, 1274,
- /* 310 */ 1274, 1274, 1306, 1210, 1344, 1344, 1353, 1359, 1268, 1344,
- /* 320 */ 1268, 1344, 1306, 1210, 1449, 1565, 1306, 1210, 1423, 1306,
- /* 330 */ 1210, 1306, 1210, 1423, 1266, 1266, 1266, 1255, 1192, 1192,
- /* 340 */ 1423, 1266, 1240, 1266, 1255, 1266, 1266, 1516, 1423, 1427,
- /* 350 */ 1427, 1423, 1324, 1319, 1324, 1319, 1324, 1319, 1324, 1319,
- /* 360 */ 1306, 1508, 1508, 1334, 1334, 1339, 1325, 1418, 1306, 1192,
- /* 370 */ 1339, 1337, 1335, 1344, 1216, 1258, 1530, 1530, 1526, 1526,
- /* 380 */ 1526, 1576, 1576, 1481, 1542, 1223, 1223, 1223, 1223, 1542,
- /* 390 */ 1242, 1242, 1224, 1224, 1223, 1542, 1192, 1192, 1192, 1192,
- /* 400 */ 1192, 1192, 1537, 1192, 1434, 1310, 1192, 1192, 1192, 1192,
- /* 410 */ 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192,
- /* 420 */ 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1364,
- /* 430 */ 1192, 1195, 1478, 1192, 1192, 1476, 1192, 1192, 1192, 1192,
- /* 440 */ 1192, 1192, 1311, 1192, 1192, 1192, 1192, 1192, 1192, 1192,
- /* 450 */ 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192,
- /* 460 */ 1192, 1567, 1192, 1192, 1192, 1192, 1192, 1192, 1448, 1447,
- /* 470 */ 1192, 1192, 1308, 1192, 1192, 1192, 1192, 1192, 1192, 1192,
- /* 480 */ 1192, 1192, 1192, 1192, 1192, 1192, 1238, 1192, 1192, 1192,
- /* 490 */ 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192,
- /* 500 */ 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192,
- /* 510 */ 1192, 1192, 1192, 1336, 1192, 1192, 1192, 1192, 1192, 1192,
- /* 520 */ 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1513, 1326,
- /* 530 */ 1192, 1192, 1558, 1192, 1192, 1192, 1192, 1192, 1192, 1192,
- /* 540 */ 1192, 1192, 1192, 1192, 1192, 1192, 1192, 1553, 1282, 1366,
- /* 550 */ 1192, 1365, 1369, 1192, 1204, 1192, 1192,
+ /* 0 */ 1651, 1651, 1651, 1479, 1244, 1355, 1244, 1244, 1244, 1479,
+ /* 10 */ 1479, 1479, 1244, 1385, 1385, 1532, 1277, 1244, 1244, 1244,
+ /* 20 */ 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1478, 1244, 1244,
+ /* 30 */ 1244, 1244, 1567, 1567, 1244, 1244, 1244, 1244, 1244, 1244,
+ /* 40 */ 1244, 1244, 1394, 1244, 1401, 1244, 1244, 1244, 1244, 1244,
+ /* 50 */ 1480, 1481, 1244, 1244, 1244, 1531, 1533, 1496, 1408, 1407,
+ /* 60 */ 1406, 1405, 1514, 1373, 1399, 1392, 1396, 1474, 1475, 1473,
+ /* 70 */ 1477, 1481, 1480, 1244, 1395, 1442, 1458, 1441, 1244, 1244,
+ /* 80 */ 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244,
+ /* 90 */ 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244,
+ /* 100 */ 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244,
+ /* 110 */ 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244,
+ /* 120 */ 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244,
+ /* 130 */ 1450, 1457, 1456, 1455, 1464, 1454, 1451, 1444, 1443, 1445,
+ /* 140 */ 1446, 1244, 1244, 1268, 1244, 1244, 1265, 1319, 1244, 1244,
+ /* 150 */ 1244, 1244, 1244, 1551, 1550, 1244, 1447, 1244, 1277, 1436,
+ /* 160 */ 1435, 1461, 1448, 1460, 1459, 1539, 1603, 1602, 1497, 1244,
+ /* 170 */ 1244, 1244, 1244, 1244, 1244, 1567, 1244, 1244, 1244, 1244,
+ /* 180 */ 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244,
+ /* 190 */ 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1375,
+ /* 200 */ 1567, 1567, 1244, 1277, 1567, 1567, 1376, 1376, 1273, 1273,
+ /* 210 */ 1379, 1244, 1546, 1346, 1346, 1346, 1346, 1355, 1346, 1244,
+ /* 220 */ 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244,
+ /* 230 */ 1244, 1244, 1244, 1244, 1536, 1534, 1244, 1244, 1244, 1244,
+ /* 240 */ 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244,
+ /* 250 */ 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244,
+ /* 260 */ 1244, 1244, 1244, 1351, 1244, 1244, 1244, 1244, 1244, 1244,
+ /* 270 */ 1244, 1244, 1244, 1244, 1244, 1596, 1244, 1509, 1333, 1351,
+ /* 280 */ 1351, 1351, 1351, 1353, 1334, 1332, 1345, 1278, 1251, 1643,
+ /* 290 */ 1411, 1400, 1352, 1400, 1640, 1398, 1411, 1411, 1398, 1411,
+ /* 300 */ 1352, 1640, 1294, 1619, 1289, 1385, 1385, 1385, 1375, 1375,
+ /* 310 */ 1375, 1375, 1379, 1379, 1476, 1352, 1345, 1244, 1643, 1643,
+ /* 320 */ 1361, 1361, 1642, 1642, 1361, 1497, 1627, 1420, 1393, 1379,
+ /* 330 */ 1322, 1393, 1379, 1328, 1328, 1328, 1328, 1361, 1262, 1398,
+ /* 340 */ 1627, 1627, 1398, 1420, 1322, 1398, 1322, 1398, 1361, 1262,
+ /* 350 */ 1513, 1637, 1361, 1262, 1487, 1361, 1262, 1361, 1262, 1487,
+ /* 360 */ 1320, 1320, 1320, 1309, 1244, 1244, 1487, 1320, 1294, 1320,
+ /* 370 */ 1309, 1320, 1320, 1585, 1244, 1491, 1491, 1487, 1361, 1577,
+ /* 380 */ 1577, 1388, 1388, 1393, 1379, 1482, 1361, 1244, 1393, 1391,
+ /* 390 */ 1389, 1398, 1312, 1599, 1599, 1595, 1595, 1595, 1648, 1648,
+ /* 400 */ 1546, 1612, 1277, 1277, 1277, 1277, 1612, 1296, 1296, 1278,
+ /* 410 */ 1278, 1277, 1612, 1244, 1244, 1244, 1244, 1244, 1244, 1607,
+ /* 420 */ 1244, 1541, 1498, 1365, 1244, 1244, 1244, 1244, 1244, 1244,
+ /* 430 */ 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1552, 1244,
+ /* 440 */ 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1425,
+ /* 450 */ 1244, 1247, 1543, 1244, 1244, 1244, 1244, 1244, 1244, 1244,
+ /* 460 */ 1244, 1402, 1403, 1366, 1244, 1244, 1244, 1244, 1244, 1244,
+ /* 470 */ 1244, 1417, 1244, 1244, 1244, 1412, 1244, 1244, 1244, 1244,
+ /* 480 */ 1244, 1244, 1244, 1244, 1639, 1244, 1244, 1244, 1244, 1244,
+ /* 490 */ 1244, 1512, 1511, 1244, 1244, 1363, 1244, 1244, 1244, 1244,
+ /* 500 */ 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1292,
+ /* 510 */ 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244,
+ /* 520 */ 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244,
+ /* 530 */ 1244, 1244, 1244, 1390, 1244, 1244, 1244, 1244, 1244, 1244,
+ /* 540 */ 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1582, 1380,
+ /* 550 */ 1244, 1244, 1244, 1244, 1630, 1244, 1244, 1244, 1244, 1244,
+ /* 560 */ 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1244, 1623,
+ /* 570 */ 1336, 1427, 1244, 1426, 1430, 1266, 1244, 1256, 1244, 1244,
};
/********** End of lemon-generated parsing tables *****************************/
@@ -160909,8 +170128,8 @@ static const YYCODETYPE yyFallback[] = {
0, /* LP => nothing */
0, /* RP => nothing */
0, /* AS => nothing */
- 59, /* WITHOUT => ID */
0, /* COMMA => nothing */
+ 59, /* WITHOUT => ID */
59, /* ABORT => ID */
59, /* ACTION => ID */
59, /* AFTER => ID */
@@ -160981,6 +170200,7 @@ static const YYCODETYPE yyFallback[] = {
59, /* TIES => ID */
59, /* GENERATED => ID */
59, /* ALWAYS => ID */
+ 59, /* MATERIALIZED => ID */
59, /* REINDEX => ID */
59, /* RENAME => ID */
59, /* CTIME_KW => ID */
@@ -160995,6 +170215,7 @@ static const YYCODETYPE yyFallback[] = {
0, /* SLASH => nothing */
0, /* REM => nothing */
0, /* CONCAT => nothing */
+ 0, /* PTR => nothing */
0, /* COLLATE => nothing */
0, /* BITNOT => nothing */
0, /* ON => nothing */
@@ -161032,6 +170253,7 @@ static const YYCODETYPE yyFallback[] = {
0, /* HAVING => nothing */
0, /* LIMIT => nothing */
0, /* WHERE => nothing */
+ 0, /* RETURNING => nothing */
0, /* INTO => nothing */
0, /* NOTHING => nothing */
0, /* FLOAT => nothing */
@@ -161063,6 +170285,7 @@ static const YYCODETYPE yyFallback[] = {
0, /* IF_NULL_ROW => nothing */
0, /* ASTERISK => nothing */
0, /* SPAN => nothing */
+ 0, /* ERROR => nothing */
0, /* SPACE => nothing */
0, /* ILLEGAL => nothing */
};
@@ -161116,9 +170339,9 @@ struct yyParser {
};
typedef struct yyParser yyParser;
+/* #include <assert.h> */
#ifndef NDEBUG
/* #include <stdio.h> */
-/* #include <assert.h> */
static FILE *yyTraceFILE = 0;
static char *yyTracePrompt = 0;
#endif /* NDEBUG */
@@ -161178,8 +170401,8 @@ static const char *const yyTokenName[] = {
/* 22 */ "LP",
/* 23 */ "RP",
/* 24 */ "AS",
- /* 25 */ "WITHOUT",
- /* 26 */ "COMMA",
+ /* 25 */ "COMMA",
+ /* 26 */ "WITHOUT",
/* 27 */ "ABORT",
/* 28 */ "ACTION",
/* 29 */ "AFTER",
@@ -161250,219 +170473,228 @@ static const char *const yyTokenName[] = {
/* 94 */ "TIES",
/* 95 */ "GENERATED",
/* 96 */ "ALWAYS",
- /* 97 */ "REINDEX",
- /* 98 */ "RENAME",
- /* 99 */ "CTIME_KW",
- /* 100 */ "ANY",
- /* 101 */ "BITAND",
- /* 102 */ "BITOR",
- /* 103 */ "LSHIFT",
- /* 104 */ "RSHIFT",
- /* 105 */ "PLUS",
- /* 106 */ "MINUS",
- /* 107 */ "STAR",
- /* 108 */ "SLASH",
- /* 109 */ "REM",
- /* 110 */ "CONCAT",
- /* 111 */ "COLLATE",
- /* 112 */ "BITNOT",
- /* 113 */ "ON",
- /* 114 */ "INDEXED",
- /* 115 */ "STRING",
- /* 116 */ "JOIN_KW",
- /* 117 */ "CONSTRAINT",
- /* 118 */ "DEFAULT",
- /* 119 */ "NULL",
- /* 120 */ "PRIMARY",
- /* 121 */ "UNIQUE",
- /* 122 */ "CHECK",
- /* 123 */ "REFERENCES",
- /* 124 */ "AUTOINCR",
- /* 125 */ "INSERT",
- /* 126 */ "DELETE",
- /* 127 */ "UPDATE",
- /* 128 */ "SET",
- /* 129 */ "DEFERRABLE",
- /* 130 */ "FOREIGN",
- /* 131 */ "DROP",
- /* 132 */ "UNION",
- /* 133 */ "ALL",
- /* 134 */ "EXCEPT",
- /* 135 */ "INTERSECT",
- /* 136 */ "SELECT",
- /* 137 */ "VALUES",
- /* 138 */ "DISTINCT",
- /* 139 */ "DOT",
- /* 140 */ "FROM",
- /* 141 */ "JOIN",
- /* 142 */ "USING",
- /* 143 */ "ORDER",
- /* 144 */ "GROUP",
- /* 145 */ "HAVING",
- /* 146 */ "LIMIT",
- /* 147 */ "WHERE",
- /* 148 */ "INTO",
- /* 149 */ "NOTHING",
- /* 150 */ "FLOAT",
- /* 151 */ "BLOB",
- /* 152 */ "INTEGER",
- /* 153 */ "VARIABLE",
- /* 154 */ "CASE",
- /* 155 */ "WHEN",
- /* 156 */ "THEN",
- /* 157 */ "ELSE",
- /* 158 */ "INDEX",
- /* 159 */ "ALTER",
- /* 160 */ "ADD",
- /* 161 */ "WINDOW",
- /* 162 */ "OVER",
- /* 163 */ "FILTER",
- /* 164 */ "COLUMN",
- /* 165 */ "AGG_FUNCTION",
- /* 166 */ "AGG_COLUMN",
- /* 167 */ "TRUEFALSE",
- /* 168 */ "ISNOT",
- /* 169 */ "FUNCTION",
- /* 170 */ "UMINUS",
- /* 171 */ "UPLUS",
- /* 172 */ "TRUTH",
- /* 173 */ "REGISTER",
- /* 174 */ "VECTOR",
- /* 175 */ "SELECT_COLUMN",
- /* 176 */ "IF_NULL_ROW",
- /* 177 */ "ASTERISK",
- /* 178 */ "SPAN",
- /* 179 */ "SPACE",
- /* 180 */ "ILLEGAL",
- /* 181 */ "input",
- /* 182 */ "cmdlist",
- /* 183 */ "ecmd",
- /* 184 */ "cmdx",
- /* 185 */ "explain",
- /* 186 */ "cmd",
- /* 187 */ "transtype",
- /* 188 */ "trans_opt",
- /* 189 */ "nm",
- /* 190 */ "savepoint_opt",
- /* 191 */ "create_table",
- /* 192 */ "create_table_args",
- /* 193 */ "createkw",
- /* 194 */ "temp",
- /* 195 */ "ifnotexists",
- /* 196 */ "dbnm",
- /* 197 */ "columnlist",
- /* 198 */ "conslist_opt",
- /* 199 */ "table_options",
- /* 200 */ "select",
- /* 201 */ "columnname",
- /* 202 */ "carglist",
- /* 203 */ "typetoken",
- /* 204 */ "typename",
- /* 205 */ "signed",
- /* 206 */ "plus_num",
- /* 207 */ "minus_num",
- /* 208 */ "scanpt",
- /* 209 */ "scantok",
- /* 210 */ "ccons",
- /* 211 */ "term",
- /* 212 */ "expr",
- /* 213 */ "onconf",
- /* 214 */ "sortorder",
- /* 215 */ "autoinc",
- /* 216 */ "eidlist_opt",
- /* 217 */ "refargs",
- /* 218 */ "defer_subclause",
- /* 219 */ "generated",
- /* 220 */ "refarg",
- /* 221 */ "refact",
- /* 222 */ "init_deferred_pred_opt",
- /* 223 */ "conslist",
- /* 224 */ "tconscomma",
- /* 225 */ "tcons",
- /* 226 */ "sortlist",
- /* 227 */ "eidlist",
- /* 228 */ "defer_subclause_opt",
- /* 229 */ "orconf",
- /* 230 */ "resolvetype",
- /* 231 */ "raisetype",
- /* 232 */ "ifexists",
- /* 233 */ "fullname",
- /* 234 */ "selectnowith",
- /* 235 */ "oneselect",
- /* 236 */ "wqlist",
- /* 237 */ "multiselect_op",
- /* 238 */ "distinct",
- /* 239 */ "selcollist",
- /* 240 */ "from",
- /* 241 */ "where_opt",
- /* 242 */ "groupby_opt",
- /* 243 */ "having_opt",
- /* 244 */ "orderby_opt",
- /* 245 */ "limit_opt",
- /* 246 */ "window_clause",
- /* 247 */ "values",
- /* 248 */ "nexprlist",
- /* 249 */ "sclp",
- /* 250 */ "as",
- /* 251 */ "seltablist",
- /* 252 */ "stl_prefix",
- /* 253 */ "joinop",
- /* 254 */ "indexed_opt",
- /* 255 */ "on_opt",
- /* 256 */ "using_opt",
- /* 257 */ "exprlist",
- /* 258 */ "xfullname",
- /* 259 */ "idlist",
- /* 260 */ "nulls",
- /* 261 */ "with",
- /* 262 */ "setlist",
- /* 263 */ "insert_cmd",
- /* 264 */ "idlist_opt",
- /* 265 */ "upsert",
- /* 266 */ "filter_over",
- /* 267 */ "likeop",
- /* 268 */ "between_op",
- /* 269 */ "in_op",
- /* 270 */ "paren_exprlist",
- /* 271 */ "case_operand",
- /* 272 */ "case_exprlist",
- /* 273 */ "case_else",
- /* 274 */ "uniqueflag",
- /* 275 */ "collate",
- /* 276 */ "vinto",
- /* 277 */ "nmnum",
- /* 278 */ "trigger_decl",
- /* 279 */ "trigger_cmd_list",
- /* 280 */ "trigger_time",
- /* 281 */ "trigger_event",
- /* 282 */ "foreach_clause",
- /* 283 */ "when_clause",
- /* 284 */ "trigger_cmd",
- /* 285 */ "trnm",
- /* 286 */ "tridxby",
- /* 287 */ "database_kw_opt",
- /* 288 */ "key_opt",
- /* 289 */ "add_column_fullname",
- /* 290 */ "kwcolumn_opt",
- /* 291 */ "create_vtab",
- /* 292 */ "vtabarglist",
- /* 293 */ "vtabarg",
- /* 294 */ "vtabargtoken",
- /* 295 */ "lp",
- /* 296 */ "anylist",
- /* 297 */ "windowdefn_list",
- /* 298 */ "windowdefn",
- /* 299 */ "window",
- /* 300 */ "frame_opt",
- /* 301 */ "part_opt",
- /* 302 */ "filter_clause",
- /* 303 */ "over_clause",
- /* 304 */ "range_or_rows",
- /* 305 */ "frame_bound",
- /* 306 */ "frame_bound_s",
- /* 307 */ "frame_bound_e",
- /* 308 */ "frame_exclude_opt",
- /* 309 */ "frame_exclude",
+ /* 97 */ "MATERIALIZED",
+ /* 98 */ "REINDEX",
+ /* 99 */ "RENAME",
+ /* 100 */ "CTIME_KW",
+ /* 101 */ "ANY",
+ /* 102 */ "BITAND",
+ /* 103 */ "BITOR",
+ /* 104 */ "LSHIFT",
+ /* 105 */ "RSHIFT",
+ /* 106 */ "PLUS",
+ /* 107 */ "MINUS",
+ /* 108 */ "STAR",
+ /* 109 */ "SLASH",
+ /* 110 */ "REM",
+ /* 111 */ "CONCAT",
+ /* 112 */ "PTR",
+ /* 113 */ "COLLATE",
+ /* 114 */ "BITNOT",
+ /* 115 */ "ON",
+ /* 116 */ "INDEXED",
+ /* 117 */ "STRING",
+ /* 118 */ "JOIN_KW",
+ /* 119 */ "CONSTRAINT",
+ /* 120 */ "DEFAULT",
+ /* 121 */ "NULL",
+ /* 122 */ "PRIMARY",
+ /* 123 */ "UNIQUE",
+ /* 124 */ "CHECK",
+ /* 125 */ "REFERENCES",
+ /* 126 */ "AUTOINCR",
+ /* 127 */ "INSERT",
+ /* 128 */ "DELETE",
+ /* 129 */ "UPDATE",
+ /* 130 */ "SET",
+ /* 131 */ "DEFERRABLE",
+ /* 132 */ "FOREIGN",
+ /* 133 */ "DROP",
+ /* 134 */ "UNION",
+ /* 135 */ "ALL",
+ /* 136 */ "EXCEPT",
+ /* 137 */ "INTERSECT",
+ /* 138 */ "SELECT",
+ /* 139 */ "VALUES",
+ /* 140 */ "DISTINCT",
+ /* 141 */ "DOT",
+ /* 142 */ "FROM",
+ /* 143 */ "JOIN",
+ /* 144 */ "USING",
+ /* 145 */ "ORDER",
+ /* 146 */ "GROUP",
+ /* 147 */ "HAVING",
+ /* 148 */ "LIMIT",
+ /* 149 */ "WHERE",
+ /* 150 */ "RETURNING",
+ /* 151 */ "INTO",
+ /* 152 */ "NOTHING",
+ /* 153 */ "FLOAT",
+ /* 154 */ "BLOB",
+ /* 155 */ "INTEGER",
+ /* 156 */ "VARIABLE",
+ /* 157 */ "CASE",
+ /* 158 */ "WHEN",
+ /* 159 */ "THEN",
+ /* 160 */ "ELSE",
+ /* 161 */ "INDEX",
+ /* 162 */ "ALTER",
+ /* 163 */ "ADD",
+ /* 164 */ "WINDOW",
+ /* 165 */ "OVER",
+ /* 166 */ "FILTER",
+ /* 167 */ "COLUMN",
+ /* 168 */ "AGG_FUNCTION",
+ /* 169 */ "AGG_COLUMN",
+ /* 170 */ "TRUEFALSE",
+ /* 171 */ "ISNOT",
+ /* 172 */ "FUNCTION",
+ /* 173 */ "UMINUS",
+ /* 174 */ "UPLUS",
+ /* 175 */ "TRUTH",
+ /* 176 */ "REGISTER",
+ /* 177 */ "VECTOR",
+ /* 178 */ "SELECT_COLUMN",
+ /* 179 */ "IF_NULL_ROW",
+ /* 180 */ "ASTERISK",
+ /* 181 */ "SPAN",
+ /* 182 */ "ERROR",
+ /* 183 */ "SPACE",
+ /* 184 */ "ILLEGAL",
+ /* 185 */ "input",
+ /* 186 */ "cmdlist",
+ /* 187 */ "ecmd",
+ /* 188 */ "cmdx",
+ /* 189 */ "explain",
+ /* 190 */ "cmd",
+ /* 191 */ "transtype",
+ /* 192 */ "trans_opt",
+ /* 193 */ "nm",
+ /* 194 */ "savepoint_opt",
+ /* 195 */ "create_table",
+ /* 196 */ "create_table_args",
+ /* 197 */ "createkw",
+ /* 198 */ "temp",
+ /* 199 */ "ifnotexists",
+ /* 200 */ "dbnm",
+ /* 201 */ "columnlist",
+ /* 202 */ "conslist_opt",
+ /* 203 */ "table_option_set",
+ /* 204 */ "select",
+ /* 205 */ "table_option",
+ /* 206 */ "columnname",
+ /* 207 */ "carglist",
+ /* 208 */ "typetoken",
+ /* 209 */ "typename",
+ /* 210 */ "signed",
+ /* 211 */ "plus_num",
+ /* 212 */ "minus_num",
+ /* 213 */ "scanpt",
+ /* 214 */ "scantok",
+ /* 215 */ "ccons",
+ /* 216 */ "term",
+ /* 217 */ "expr",
+ /* 218 */ "onconf",
+ /* 219 */ "sortorder",
+ /* 220 */ "autoinc",
+ /* 221 */ "eidlist_opt",
+ /* 222 */ "refargs",
+ /* 223 */ "defer_subclause",
+ /* 224 */ "generated",
+ /* 225 */ "refarg",
+ /* 226 */ "refact",
+ /* 227 */ "init_deferred_pred_opt",
+ /* 228 */ "conslist",
+ /* 229 */ "tconscomma",
+ /* 230 */ "tcons",
+ /* 231 */ "sortlist",
+ /* 232 */ "eidlist",
+ /* 233 */ "defer_subclause_opt",
+ /* 234 */ "orconf",
+ /* 235 */ "resolvetype",
+ /* 236 */ "raisetype",
+ /* 237 */ "ifexists",
+ /* 238 */ "fullname",
+ /* 239 */ "selectnowith",
+ /* 240 */ "oneselect",
+ /* 241 */ "wqlist",
+ /* 242 */ "multiselect_op",
+ /* 243 */ "distinct",
+ /* 244 */ "selcollist",
+ /* 245 */ "from",
+ /* 246 */ "where_opt",
+ /* 247 */ "groupby_opt",
+ /* 248 */ "having_opt",
+ /* 249 */ "orderby_opt",
+ /* 250 */ "limit_opt",
+ /* 251 */ "window_clause",
+ /* 252 */ "values",
+ /* 253 */ "nexprlist",
+ /* 254 */ "sclp",
+ /* 255 */ "as",
+ /* 256 */ "seltablist",
+ /* 257 */ "stl_prefix",
+ /* 258 */ "joinop",
+ /* 259 */ "on_using",
+ /* 260 */ "indexed_by",
+ /* 261 */ "exprlist",
+ /* 262 */ "xfullname",
+ /* 263 */ "idlist",
+ /* 264 */ "indexed_opt",
+ /* 265 */ "nulls",
+ /* 266 */ "with",
+ /* 267 */ "where_opt_ret",
+ /* 268 */ "setlist",
+ /* 269 */ "insert_cmd",
+ /* 270 */ "idlist_opt",
+ /* 271 */ "upsert",
+ /* 272 */ "returning",
+ /* 273 */ "filter_over",
+ /* 274 */ "likeop",
+ /* 275 */ "between_op",
+ /* 276 */ "in_op",
+ /* 277 */ "paren_exprlist",
+ /* 278 */ "case_operand",
+ /* 279 */ "case_exprlist",
+ /* 280 */ "case_else",
+ /* 281 */ "uniqueflag",
+ /* 282 */ "collate",
+ /* 283 */ "vinto",
+ /* 284 */ "nmnum",
+ /* 285 */ "trigger_decl",
+ /* 286 */ "trigger_cmd_list",
+ /* 287 */ "trigger_time",
+ /* 288 */ "trigger_event",
+ /* 289 */ "foreach_clause",
+ /* 290 */ "when_clause",
+ /* 291 */ "trigger_cmd",
+ /* 292 */ "trnm",
+ /* 293 */ "tridxby",
+ /* 294 */ "database_kw_opt",
+ /* 295 */ "key_opt",
+ /* 296 */ "add_column_fullname",
+ /* 297 */ "kwcolumn_opt",
+ /* 298 */ "create_vtab",
+ /* 299 */ "vtabarglist",
+ /* 300 */ "vtabarg",
+ /* 301 */ "vtabargtoken",
+ /* 302 */ "lp",
+ /* 303 */ "anylist",
+ /* 304 */ "wqitem",
+ /* 305 */ "wqas",
+ /* 306 */ "windowdefn_list",
+ /* 307 */ "windowdefn",
+ /* 308 */ "window",
+ /* 309 */ "frame_opt",
+ /* 310 */ "part_opt",
+ /* 311 */ "filter_clause",
+ /* 312 */ "over_clause",
+ /* 313 */ "range_or_rows",
+ /* 314 */ "frame_bound",
+ /* 315 */ "frame_bound_s",
+ /* 316 */ "frame_bound_e",
+ /* 317 */ "frame_exclude_opt",
+ /* 318 */ "frame_exclude",
};
#endif /* defined(YYCOVERAGE) || !defined(NDEBUG) */
@@ -161489,372 +170721,392 @@ static const char *const yyRuleName[] = {
/* 16 */ "ifnotexists ::= IF NOT EXISTS",
/* 17 */ "temp ::= TEMP",
/* 18 */ "temp ::=",
- /* 19 */ "create_table_args ::= LP columnlist conslist_opt RP table_options",
+ /* 19 */ "create_table_args ::= LP columnlist conslist_opt RP table_option_set",
/* 20 */ "create_table_args ::= AS select",
- /* 21 */ "table_options ::=",
- /* 22 */ "table_options ::= WITHOUT nm",
- /* 23 */ "columnname ::= nm typetoken",
- /* 24 */ "typetoken ::=",
- /* 25 */ "typetoken ::= typename LP signed RP",
- /* 26 */ "typetoken ::= typename LP signed COMMA signed RP",
- /* 27 */ "typename ::= typename ID|STRING",
- /* 28 */ "scanpt ::=",
- /* 29 */ "scantok ::=",
- /* 30 */ "ccons ::= CONSTRAINT nm",
- /* 31 */ "ccons ::= DEFAULT scantok term",
- /* 32 */ "ccons ::= DEFAULT LP expr RP",
- /* 33 */ "ccons ::= DEFAULT PLUS scantok term",
- /* 34 */ "ccons ::= DEFAULT MINUS scantok term",
- /* 35 */ "ccons ::= DEFAULT scantok ID|INDEXED",
- /* 36 */ "ccons ::= NOT NULL onconf",
- /* 37 */ "ccons ::= PRIMARY KEY sortorder onconf autoinc",
- /* 38 */ "ccons ::= UNIQUE onconf",
- /* 39 */ "ccons ::= CHECK LP expr RP",
- /* 40 */ "ccons ::= REFERENCES nm eidlist_opt refargs",
- /* 41 */ "ccons ::= defer_subclause",
- /* 42 */ "ccons ::= COLLATE ID|STRING",
- /* 43 */ "generated ::= LP expr RP",
- /* 44 */ "generated ::= LP expr RP ID",
- /* 45 */ "autoinc ::=",
- /* 46 */ "autoinc ::= AUTOINCR",
- /* 47 */ "refargs ::=",
- /* 48 */ "refargs ::= refargs refarg",
- /* 49 */ "refarg ::= MATCH nm",
- /* 50 */ "refarg ::= ON INSERT refact",
- /* 51 */ "refarg ::= ON DELETE refact",
- /* 52 */ "refarg ::= ON UPDATE refact",
- /* 53 */ "refact ::= SET NULL",
- /* 54 */ "refact ::= SET DEFAULT",
- /* 55 */ "refact ::= CASCADE",
- /* 56 */ "refact ::= RESTRICT",
- /* 57 */ "refact ::= NO ACTION",
- /* 58 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt",
- /* 59 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt",
- /* 60 */ "init_deferred_pred_opt ::=",
- /* 61 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED",
- /* 62 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE",
- /* 63 */ "conslist_opt ::=",
- /* 64 */ "tconscomma ::= COMMA",
- /* 65 */ "tcons ::= CONSTRAINT nm",
- /* 66 */ "tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf",
- /* 67 */ "tcons ::= UNIQUE LP sortlist RP onconf",
- /* 68 */ "tcons ::= CHECK LP expr RP onconf",
- /* 69 */ "tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt",
- /* 70 */ "defer_subclause_opt ::=",
- /* 71 */ "onconf ::=",
- /* 72 */ "onconf ::= ON CONFLICT resolvetype",
- /* 73 */ "orconf ::=",
- /* 74 */ "orconf ::= OR resolvetype",
- /* 75 */ "resolvetype ::= IGNORE",
- /* 76 */ "resolvetype ::= REPLACE",
- /* 77 */ "cmd ::= DROP TABLE ifexists fullname",
- /* 78 */ "ifexists ::= IF EXISTS",
- /* 79 */ "ifexists ::=",
- /* 80 */ "cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select",
- /* 81 */ "cmd ::= DROP VIEW ifexists fullname",
- /* 82 */ "cmd ::= select",
- /* 83 */ "select ::= WITH wqlist selectnowith",
- /* 84 */ "select ::= WITH RECURSIVE wqlist selectnowith",
- /* 85 */ "select ::= selectnowith",
- /* 86 */ "selectnowith ::= selectnowith multiselect_op oneselect",
- /* 87 */ "multiselect_op ::= UNION",
- /* 88 */ "multiselect_op ::= UNION ALL",
- /* 89 */ "multiselect_op ::= EXCEPT|INTERSECT",
- /* 90 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt",
- /* 91 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt",
- /* 92 */ "values ::= VALUES LP nexprlist RP",
- /* 93 */ "values ::= values COMMA LP nexprlist RP",
- /* 94 */ "distinct ::= DISTINCT",
- /* 95 */ "distinct ::= ALL",
- /* 96 */ "distinct ::=",
- /* 97 */ "sclp ::=",
- /* 98 */ "selcollist ::= sclp scanpt expr scanpt as",
- /* 99 */ "selcollist ::= sclp scanpt STAR",
- /* 100 */ "selcollist ::= sclp scanpt nm DOT STAR",
- /* 101 */ "as ::= AS nm",
- /* 102 */ "as ::=",
- /* 103 */ "from ::=",
- /* 104 */ "from ::= FROM seltablist",
- /* 105 */ "stl_prefix ::= seltablist joinop",
- /* 106 */ "stl_prefix ::=",
- /* 107 */ "seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt",
- /* 108 */ "seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt",
- /* 109 */ "seltablist ::= stl_prefix LP select RP as on_opt using_opt",
- /* 110 */ "seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt",
- /* 111 */ "dbnm ::=",
- /* 112 */ "dbnm ::= DOT nm",
- /* 113 */ "fullname ::= nm",
- /* 114 */ "fullname ::= nm DOT nm",
- /* 115 */ "xfullname ::= nm",
- /* 116 */ "xfullname ::= nm DOT nm",
- /* 117 */ "xfullname ::= nm DOT nm AS nm",
- /* 118 */ "xfullname ::= nm AS nm",
- /* 119 */ "joinop ::= COMMA|JOIN",
- /* 120 */ "joinop ::= JOIN_KW JOIN",
- /* 121 */ "joinop ::= JOIN_KW nm JOIN",
- /* 122 */ "joinop ::= JOIN_KW nm nm JOIN",
- /* 123 */ "on_opt ::= ON expr",
- /* 124 */ "on_opt ::=",
- /* 125 */ "indexed_opt ::=",
- /* 126 */ "indexed_opt ::= INDEXED BY nm",
- /* 127 */ "indexed_opt ::= NOT INDEXED",
- /* 128 */ "using_opt ::= USING LP idlist RP",
- /* 129 */ "using_opt ::=",
- /* 130 */ "orderby_opt ::=",
- /* 131 */ "orderby_opt ::= ORDER BY sortlist",
- /* 132 */ "sortlist ::= sortlist COMMA expr sortorder nulls",
- /* 133 */ "sortlist ::= expr sortorder nulls",
- /* 134 */ "sortorder ::= ASC",
- /* 135 */ "sortorder ::= DESC",
- /* 136 */ "sortorder ::=",
- /* 137 */ "nulls ::= NULLS FIRST",
- /* 138 */ "nulls ::= NULLS LAST",
- /* 139 */ "nulls ::=",
- /* 140 */ "groupby_opt ::=",
- /* 141 */ "groupby_opt ::= GROUP BY nexprlist",
- /* 142 */ "having_opt ::=",
- /* 143 */ "having_opt ::= HAVING expr",
- /* 144 */ "limit_opt ::=",
- /* 145 */ "limit_opt ::= LIMIT expr",
- /* 146 */ "limit_opt ::= LIMIT expr OFFSET expr",
- /* 147 */ "limit_opt ::= LIMIT expr COMMA expr",
- /* 148 */ "cmd ::= with DELETE FROM xfullname indexed_opt where_opt orderby_opt limit_opt",
- /* 149 */ "where_opt ::=",
- /* 150 */ "where_opt ::= WHERE expr",
- /* 151 */ "cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt orderby_opt limit_opt",
- /* 152 */ "setlist ::= setlist COMMA nm EQ expr",
- /* 153 */ "setlist ::= setlist COMMA LP idlist RP EQ expr",
- /* 154 */ "setlist ::= nm EQ expr",
- /* 155 */ "setlist ::= LP idlist RP EQ expr",
- /* 156 */ "cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert",
- /* 157 */ "cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES",
- /* 158 */ "upsert ::=",
- /* 159 */ "upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt",
- /* 160 */ "upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING",
- /* 161 */ "upsert ::= ON CONFLICT DO NOTHING",
- /* 162 */ "insert_cmd ::= INSERT orconf",
- /* 163 */ "insert_cmd ::= REPLACE",
- /* 164 */ "idlist_opt ::=",
- /* 165 */ "idlist_opt ::= LP idlist RP",
- /* 166 */ "idlist ::= idlist COMMA nm",
- /* 167 */ "idlist ::= nm",
- /* 168 */ "expr ::= LP expr RP",
- /* 169 */ "expr ::= ID|INDEXED",
- /* 170 */ "expr ::= JOIN_KW",
- /* 171 */ "expr ::= nm DOT nm",
- /* 172 */ "expr ::= nm DOT nm DOT nm",
- /* 173 */ "term ::= NULL|FLOAT|BLOB",
- /* 174 */ "term ::= STRING",
- /* 175 */ "term ::= INTEGER",
- /* 176 */ "expr ::= VARIABLE",
- /* 177 */ "expr ::= expr COLLATE ID|STRING",
- /* 178 */ "expr ::= CAST LP expr AS typetoken RP",
- /* 179 */ "expr ::= ID|INDEXED LP distinct exprlist RP",
- /* 180 */ "expr ::= ID|INDEXED LP STAR RP",
- /* 181 */ "expr ::= ID|INDEXED LP distinct exprlist RP filter_over",
- /* 182 */ "expr ::= ID|INDEXED LP STAR RP filter_over",
- /* 183 */ "term ::= CTIME_KW",
- /* 184 */ "expr ::= LP nexprlist COMMA expr RP",
- /* 185 */ "expr ::= expr AND expr",
- /* 186 */ "expr ::= expr OR expr",
- /* 187 */ "expr ::= expr LT|GT|GE|LE expr",
- /* 188 */ "expr ::= expr EQ|NE expr",
- /* 189 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr",
- /* 190 */ "expr ::= expr PLUS|MINUS expr",
- /* 191 */ "expr ::= expr STAR|SLASH|REM expr",
- /* 192 */ "expr ::= expr CONCAT expr",
- /* 193 */ "likeop ::= NOT LIKE_KW|MATCH",
- /* 194 */ "expr ::= expr likeop expr",
- /* 195 */ "expr ::= expr likeop expr ESCAPE expr",
- /* 196 */ "expr ::= expr ISNULL|NOTNULL",
- /* 197 */ "expr ::= expr NOT NULL",
- /* 198 */ "expr ::= expr IS expr",
- /* 199 */ "expr ::= expr IS NOT expr",
- /* 200 */ "expr ::= NOT expr",
- /* 201 */ "expr ::= BITNOT expr",
- /* 202 */ "expr ::= PLUS|MINUS expr",
- /* 203 */ "between_op ::= BETWEEN",
- /* 204 */ "between_op ::= NOT BETWEEN",
- /* 205 */ "expr ::= expr between_op expr AND expr",
- /* 206 */ "in_op ::= IN",
- /* 207 */ "in_op ::= NOT IN",
- /* 208 */ "expr ::= expr in_op LP exprlist RP",
- /* 209 */ "expr ::= LP select RP",
- /* 210 */ "expr ::= expr in_op LP select RP",
- /* 211 */ "expr ::= expr in_op nm dbnm paren_exprlist",
- /* 212 */ "expr ::= EXISTS LP select RP",
- /* 213 */ "expr ::= CASE case_operand case_exprlist case_else END",
- /* 214 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr",
- /* 215 */ "case_exprlist ::= WHEN expr THEN expr",
- /* 216 */ "case_else ::= ELSE expr",
- /* 217 */ "case_else ::=",
- /* 218 */ "case_operand ::= expr",
- /* 219 */ "case_operand ::=",
- /* 220 */ "exprlist ::=",
- /* 221 */ "nexprlist ::= nexprlist COMMA expr",
- /* 222 */ "nexprlist ::= expr",
- /* 223 */ "paren_exprlist ::=",
- /* 224 */ "paren_exprlist ::= LP exprlist RP",
- /* 225 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt",
- /* 226 */ "uniqueflag ::= UNIQUE",
- /* 227 */ "uniqueflag ::=",
- /* 228 */ "eidlist_opt ::=",
- /* 229 */ "eidlist_opt ::= LP eidlist RP",
- /* 230 */ "eidlist ::= eidlist COMMA nm collate sortorder",
- /* 231 */ "eidlist ::= nm collate sortorder",
- /* 232 */ "collate ::=",
- /* 233 */ "collate ::= COLLATE ID|STRING",
- /* 234 */ "cmd ::= DROP INDEX ifexists fullname",
- /* 235 */ "cmd ::= VACUUM vinto",
- /* 236 */ "cmd ::= VACUUM nm vinto",
- /* 237 */ "vinto ::= INTO expr",
- /* 238 */ "vinto ::=",
- /* 239 */ "cmd ::= PRAGMA nm dbnm",
- /* 240 */ "cmd ::= PRAGMA nm dbnm EQ nmnum",
- /* 241 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP",
- /* 242 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
- /* 243 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP",
- /* 244 */ "plus_num ::= PLUS INTEGER|FLOAT",
- /* 245 */ "minus_num ::= MINUS INTEGER|FLOAT",
- /* 246 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END",
- /* 247 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
- /* 248 */ "trigger_time ::= BEFORE|AFTER",
- /* 249 */ "trigger_time ::= INSTEAD OF",
- /* 250 */ "trigger_time ::=",
- /* 251 */ "trigger_event ::= DELETE|INSERT",
- /* 252 */ "trigger_event ::= UPDATE",
- /* 253 */ "trigger_event ::= UPDATE OF idlist",
- /* 254 */ "when_clause ::=",
- /* 255 */ "when_clause ::= WHEN expr",
- /* 256 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI",
- /* 257 */ "trigger_cmd_list ::= trigger_cmd SEMI",
- /* 258 */ "trnm ::= nm DOT nm",
- /* 259 */ "tridxby ::= INDEXED BY nm",
- /* 260 */ "tridxby ::= NOT INDEXED",
- /* 261 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt",
- /* 262 */ "trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt",
- /* 263 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt",
- /* 264 */ "trigger_cmd ::= scanpt select scanpt",
- /* 265 */ "expr ::= RAISE LP IGNORE RP",
- /* 266 */ "expr ::= RAISE LP raisetype COMMA nm RP",
- /* 267 */ "raisetype ::= ROLLBACK",
- /* 268 */ "raisetype ::= ABORT",
- /* 269 */ "raisetype ::= FAIL",
- /* 270 */ "cmd ::= DROP TRIGGER ifexists fullname",
- /* 271 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
- /* 272 */ "cmd ::= DETACH database_kw_opt expr",
- /* 273 */ "key_opt ::=",
- /* 274 */ "key_opt ::= KEY expr",
- /* 275 */ "cmd ::= REINDEX",
- /* 276 */ "cmd ::= REINDEX nm dbnm",
- /* 277 */ "cmd ::= ANALYZE",
- /* 278 */ "cmd ::= ANALYZE nm dbnm",
- /* 279 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
- /* 280 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist",
- /* 281 */ "add_column_fullname ::= fullname",
- /* 282 */ "cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm",
- /* 283 */ "cmd ::= create_vtab",
- /* 284 */ "cmd ::= create_vtab LP vtabarglist RP",
- /* 285 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm",
- /* 286 */ "vtabarg ::=",
- /* 287 */ "vtabargtoken ::= ANY",
- /* 288 */ "vtabargtoken ::= lp anylist RP",
- /* 289 */ "lp ::= LP",
- /* 290 */ "with ::= WITH wqlist",
- /* 291 */ "with ::= WITH RECURSIVE wqlist",
- /* 292 */ "wqlist ::= nm eidlist_opt AS LP select RP",
- /* 293 */ "wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP",
- /* 294 */ "windowdefn_list ::= windowdefn",
- /* 295 */ "windowdefn_list ::= windowdefn_list COMMA windowdefn",
- /* 296 */ "windowdefn ::= nm AS LP window RP",
- /* 297 */ "window ::= PARTITION BY nexprlist orderby_opt frame_opt",
- /* 298 */ "window ::= nm PARTITION BY nexprlist orderby_opt frame_opt",
- /* 299 */ "window ::= ORDER BY sortlist frame_opt",
- /* 300 */ "window ::= nm ORDER BY sortlist frame_opt",
- /* 301 */ "window ::= frame_opt",
- /* 302 */ "window ::= nm frame_opt",
- /* 303 */ "frame_opt ::=",
- /* 304 */ "frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt",
- /* 305 */ "frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt",
- /* 306 */ "range_or_rows ::= RANGE|ROWS|GROUPS",
- /* 307 */ "frame_bound_s ::= frame_bound",
- /* 308 */ "frame_bound_s ::= UNBOUNDED PRECEDING",
- /* 309 */ "frame_bound_e ::= frame_bound",
- /* 310 */ "frame_bound_e ::= UNBOUNDED FOLLOWING",
- /* 311 */ "frame_bound ::= expr PRECEDING|FOLLOWING",
- /* 312 */ "frame_bound ::= CURRENT ROW",
- /* 313 */ "frame_exclude_opt ::=",
- /* 314 */ "frame_exclude_opt ::= EXCLUDE frame_exclude",
- /* 315 */ "frame_exclude ::= NO OTHERS",
- /* 316 */ "frame_exclude ::= CURRENT ROW",
- /* 317 */ "frame_exclude ::= GROUP|TIES",
- /* 318 */ "window_clause ::= WINDOW windowdefn_list",
- /* 319 */ "filter_over ::= filter_clause over_clause",
- /* 320 */ "filter_over ::= over_clause",
- /* 321 */ "filter_over ::= filter_clause",
- /* 322 */ "over_clause ::= OVER LP window RP",
- /* 323 */ "over_clause ::= OVER nm",
- /* 324 */ "filter_clause ::= FILTER LP WHERE expr RP",
- /* 325 */ "input ::= cmdlist",
- /* 326 */ "cmdlist ::= cmdlist ecmd",
- /* 327 */ "cmdlist ::= ecmd",
- /* 328 */ "ecmd ::= SEMI",
- /* 329 */ "ecmd ::= cmdx SEMI",
- /* 330 */ "ecmd ::= explain cmdx SEMI",
- /* 331 */ "trans_opt ::=",
- /* 332 */ "trans_opt ::= TRANSACTION",
- /* 333 */ "trans_opt ::= TRANSACTION nm",
- /* 334 */ "savepoint_opt ::= SAVEPOINT",
- /* 335 */ "savepoint_opt ::=",
- /* 336 */ "cmd ::= create_table create_table_args",
- /* 337 */ "columnlist ::= columnlist COMMA columnname carglist",
- /* 338 */ "columnlist ::= columnname carglist",
- /* 339 */ "nm ::= ID|INDEXED",
- /* 340 */ "nm ::= STRING",
- /* 341 */ "nm ::= JOIN_KW",
- /* 342 */ "typetoken ::= typename",
- /* 343 */ "typename ::= ID|STRING",
- /* 344 */ "signed ::= plus_num",
- /* 345 */ "signed ::= minus_num",
- /* 346 */ "carglist ::= carglist ccons",
- /* 347 */ "carglist ::=",
- /* 348 */ "ccons ::= NULL onconf",
- /* 349 */ "ccons ::= GENERATED ALWAYS AS generated",
- /* 350 */ "ccons ::= AS generated",
- /* 351 */ "conslist_opt ::= COMMA conslist",
- /* 352 */ "conslist ::= conslist tconscomma tcons",
- /* 353 */ "conslist ::= tcons",
- /* 354 */ "tconscomma ::=",
- /* 355 */ "defer_subclause_opt ::= defer_subclause",
- /* 356 */ "resolvetype ::= raisetype",
- /* 357 */ "selectnowith ::= oneselect",
- /* 358 */ "oneselect ::= values",
- /* 359 */ "sclp ::= selcollist COMMA",
- /* 360 */ "as ::= ID|STRING",
- /* 361 */ "expr ::= term",
- /* 362 */ "likeop ::= LIKE_KW|MATCH",
- /* 363 */ "exprlist ::= nexprlist",
- /* 364 */ "nmnum ::= plus_num",
- /* 365 */ "nmnum ::= nm",
- /* 366 */ "nmnum ::= ON",
- /* 367 */ "nmnum ::= DELETE",
- /* 368 */ "nmnum ::= DEFAULT",
- /* 369 */ "plus_num ::= INTEGER|FLOAT",
- /* 370 */ "foreach_clause ::=",
- /* 371 */ "foreach_clause ::= FOR EACH ROW",
- /* 372 */ "trnm ::= nm",
- /* 373 */ "tridxby ::=",
- /* 374 */ "database_kw_opt ::= DATABASE",
- /* 375 */ "database_kw_opt ::=",
- /* 376 */ "kwcolumn_opt ::=",
- /* 377 */ "kwcolumn_opt ::= COLUMNKW",
- /* 378 */ "vtabarglist ::= vtabarg",
- /* 379 */ "vtabarglist ::= vtabarglist COMMA vtabarg",
- /* 380 */ "vtabarg ::= vtabarg vtabargtoken",
- /* 381 */ "anylist ::=",
- /* 382 */ "anylist ::= anylist LP anylist RP",
- /* 383 */ "anylist ::= anylist ANY",
- /* 384 */ "with ::=",
+ /* 21 */ "table_option_set ::=",
+ /* 22 */ "table_option_set ::= table_option_set COMMA table_option",
+ /* 23 */ "table_option ::= WITHOUT nm",
+ /* 24 */ "table_option ::= nm",
+ /* 25 */ "columnname ::= nm typetoken",
+ /* 26 */ "typetoken ::=",
+ /* 27 */ "typetoken ::= typename LP signed RP",
+ /* 28 */ "typetoken ::= typename LP signed COMMA signed RP",
+ /* 29 */ "typename ::= typename ID|STRING",
+ /* 30 */ "scanpt ::=",
+ /* 31 */ "scantok ::=",
+ /* 32 */ "ccons ::= CONSTRAINT nm",
+ /* 33 */ "ccons ::= DEFAULT scantok term",
+ /* 34 */ "ccons ::= DEFAULT LP expr RP",
+ /* 35 */ "ccons ::= DEFAULT PLUS scantok term",
+ /* 36 */ "ccons ::= DEFAULT MINUS scantok term",
+ /* 37 */ "ccons ::= DEFAULT scantok ID|INDEXED",
+ /* 38 */ "ccons ::= NOT NULL onconf",
+ /* 39 */ "ccons ::= PRIMARY KEY sortorder onconf autoinc",
+ /* 40 */ "ccons ::= UNIQUE onconf",
+ /* 41 */ "ccons ::= CHECK LP expr RP",
+ /* 42 */ "ccons ::= REFERENCES nm eidlist_opt refargs",
+ /* 43 */ "ccons ::= defer_subclause",
+ /* 44 */ "ccons ::= COLLATE ID|STRING",
+ /* 45 */ "generated ::= LP expr RP",
+ /* 46 */ "generated ::= LP expr RP ID",
+ /* 47 */ "autoinc ::=",
+ /* 48 */ "autoinc ::= AUTOINCR",
+ /* 49 */ "refargs ::=",
+ /* 50 */ "refargs ::= refargs refarg",
+ /* 51 */ "refarg ::= MATCH nm",
+ /* 52 */ "refarg ::= ON INSERT refact",
+ /* 53 */ "refarg ::= ON DELETE refact",
+ /* 54 */ "refarg ::= ON UPDATE refact",
+ /* 55 */ "refact ::= SET NULL",
+ /* 56 */ "refact ::= SET DEFAULT",
+ /* 57 */ "refact ::= CASCADE",
+ /* 58 */ "refact ::= RESTRICT",
+ /* 59 */ "refact ::= NO ACTION",
+ /* 60 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt",
+ /* 61 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt",
+ /* 62 */ "init_deferred_pred_opt ::=",
+ /* 63 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED",
+ /* 64 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE",
+ /* 65 */ "conslist_opt ::=",
+ /* 66 */ "tconscomma ::= COMMA",
+ /* 67 */ "tcons ::= CONSTRAINT nm",
+ /* 68 */ "tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf",
+ /* 69 */ "tcons ::= UNIQUE LP sortlist RP onconf",
+ /* 70 */ "tcons ::= CHECK LP expr RP onconf",
+ /* 71 */ "tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt",
+ /* 72 */ "defer_subclause_opt ::=",
+ /* 73 */ "onconf ::=",
+ /* 74 */ "onconf ::= ON CONFLICT resolvetype",
+ /* 75 */ "orconf ::=",
+ /* 76 */ "orconf ::= OR resolvetype",
+ /* 77 */ "resolvetype ::= IGNORE",
+ /* 78 */ "resolvetype ::= REPLACE",
+ /* 79 */ "cmd ::= DROP TABLE ifexists fullname",
+ /* 80 */ "ifexists ::= IF EXISTS",
+ /* 81 */ "ifexists ::=",
+ /* 82 */ "cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select",
+ /* 83 */ "cmd ::= DROP VIEW ifexists fullname",
+ /* 84 */ "cmd ::= select",
+ /* 85 */ "select ::= WITH wqlist selectnowith",
+ /* 86 */ "select ::= WITH RECURSIVE wqlist selectnowith",
+ /* 87 */ "select ::= selectnowith",
+ /* 88 */ "selectnowith ::= selectnowith multiselect_op oneselect",
+ /* 89 */ "multiselect_op ::= UNION",
+ /* 90 */ "multiselect_op ::= UNION ALL",
+ /* 91 */ "multiselect_op ::= EXCEPT|INTERSECT",
+ /* 92 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt",
+ /* 93 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt",
+ /* 94 */ "values ::= VALUES LP nexprlist RP",
+ /* 95 */ "values ::= values COMMA LP nexprlist RP",
+ /* 96 */ "distinct ::= DISTINCT",
+ /* 97 */ "distinct ::= ALL",
+ /* 98 */ "distinct ::=",
+ /* 99 */ "sclp ::=",
+ /* 100 */ "selcollist ::= sclp scanpt expr scanpt as",
+ /* 101 */ "selcollist ::= sclp scanpt STAR",
+ /* 102 */ "selcollist ::= sclp scanpt nm DOT STAR",
+ /* 103 */ "as ::= AS nm",
+ /* 104 */ "as ::=",
+ /* 105 */ "from ::=",
+ /* 106 */ "from ::= FROM seltablist",
+ /* 107 */ "stl_prefix ::= seltablist joinop",
+ /* 108 */ "stl_prefix ::=",
+ /* 109 */ "seltablist ::= stl_prefix nm dbnm as on_using",
+ /* 110 */ "seltablist ::= stl_prefix nm dbnm as indexed_by on_using",
+ /* 111 */ "seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using",
+ /* 112 */ "seltablist ::= stl_prefix LP select RP as on_using",
+ /* 113 */ "seltablist ::= stl_prefix LP seltablist RP as on_using",
+ /* 114 */ "dbnm ::=",
+ /* 115 */ "dbnm ::= DOT nm",
+ /* 116 */ "fullname ::= nm",
+ /* 117 */ "fullname ::= nm DOT nm",
+ /* 118 */ "xfullname ::= nm",
+ /* 119 */ "xfullname ::= nm DOT nm",
+ /* 120 */ "xfullname ::= nm DOT nm AS nm",
+ /* 121 */ "xfullname ::= nm AS nm",
+ /* 122 */ "joinop ::= COMMA|JOIN",
+ /* 123 */ "joinop ::= JOIN_KW JOIN",
+ /* 124 */ "joinop ::= JOIN_KW nm JOIN",
+ /* 125 */ "joinop ::= JOIN_KW nm nm JOIN",
+ /* 126 */ "on_using ::= ON expr",
+ /* 127 */ "on_using ::= USING LP idlist RP",
+ /* 128 */ "on_using ::=",
+ /* 129 */ "indexed_opt ::=",
+ /* 130 */ "indexed_by ::= INDEXED BY nm",
+ /* 131 */ "indexed_by ::= NOT INDEXED",
+ /* 132 */ "orderby_opt ::=",
+ /* 133 */ "orderby_opt ::= ORDER BY sortlist",
+ /* 134 */ "sortlist ::= sortlist COMMA expr sortorder nulls",
+ /* 135 */ "sortlist ::= expr sortorder nulls",
+ /* 136 */ "sortorder ::= ASC",
+ /* 137 */ "sortorder ::= DESC",
+ /* 138 */ "sortorder ::=",
+ /* 139 */ "nulls ::= NULLS FIRST",
+ /* 140 */ "nulls ::= NULLS LAST",
+ /* 141 */ "nulls ::=",
+ /* 142 */ "groupby_opt ::=",
+ /* 143 */ "groupby_opt ::= GROUP BY nexprlist",
+ /* 144 */ "having_opt ::=",
+ /* 145 */ "having_opt ::= HAVING expr",
+ /* 146 */ "limit_opt ::=",
+ /* 147 */ "limit_opt ::= LIMIT expr",
+ /* 148 */ "limit_opt ::= LIMIT expr OFFSET expr",
+ /* 149 */ "limit_opt ::= LIMIT expr COMMA expr",
+ /* 150 */ "cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret orderby_opt limit_opt",
+ /* 151 */ "where_opt ::=",
+ /* 152 */ "where_opt ::= WHERE expr",
+ /* 153 */ "where_opt_ret ::=",
+ /* 154 */ "where_opt_ret ::= WHERE expr",
+ /* 155 */ "where_opt_ret ::= RETURNING selcollist",
+ /* 156 */ "where_opt_ret ::= WHERE expr RETURNING selcollist",
+ /* 157 */ "cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret orderby_opt limit_opt",
+ /* 158 */ "setlist ::= setlist COMMA nm EQ expr",
+ /* 159 */ "setlist ::= setlist COMMA LP idlist RP EQ expr",
+ /* 160 */ "setlist ::= nm EQ expr",
+ /* 161 */ "setlist ::= LP idlist RP EQ expr",
+ /* 162 */ "cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert",
+ /* 163 */ "cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning",
+ /* 164 */ "upsert ::=",
+ /* 165 */ "upsert ::= RETURNING selcollist",
+ /* 166 */ "upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert",
+ /* 167 */ "upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert",
+ /* 168 */ "upsert ::= ON CONFLICT DO NOTHING returning",
+ /* 169 */ "upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning",
+ /* 170 */ "returning ::= RETURNING selcollist",
+ /* 171 */ "insert_cmd ::= INSERT orconf",
+ /* 172 */ "insert_cmd ::= REPLACE",
+ /* 173 */ "idlist_opt ::=",
+ /* 174 */ "idlist_opt ::= LP idlist RP",
+ /* 175 */ "idlist ::= idlist COMMA nm",
+ /* 176 */ "idlist ::= nm",
+ /* 177 */ "expr ::= LP expr RP",
+ /* 178 */ "expr ::= ID|INDEXED",
+ /* 179 */ "expr ::= JOIN_KW",
+ /* 180 */ "expr ::= nm DOT nm",
+ /* 181 */ "expr ::= nm DOT nm DOT nm",
+ /* 182 */ "term ::= NULL|FLOAT|BLOB",
+ /* 183 */ "term ::= STRING",
+ /* 184 */ "term ::= INTEGER",
+ /* 185 */ "expr ::= VARIABLE",
+ /* 186 */ "expr ::= expr COLLATE ID|STRING",
+ /* 187 */ "expr ::= CAST LP expr AS typetoken RP",
+ /* 188 */ "expr ::= ID|INDEXED LP distinct exprlist RP",
+ /* 189 */ "expr ::= ID|INDEXED LP STAR RP",
+ /* 190 */ "expr ::= ID|INDEXED LP distinct exprlist RP filter_over",
+ /* 191 */ "expr ::= ID|INDEXED LP STAR RP filter_over",
+ /* 192 */ "term ::= CTIME_KW",
+ /* 193 */ "expr ::= LP nexprlist COMMA expr RP",
+ /* 194 */ "expr ::= expr AND expr",
+ /* 195 */ "expr ::= expr OR expr",
+ /* 196 */ "expr ::= expr LT|GT|GE|LE expr",
+ /* 197 */ "expr ::= expr EQ|NE expr",
+ /* 198 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr",
+ /* 199 */ "expr ::= expr PLUS|MINUS expr",
+ /* 200 */ "expr ::= expr STAR|SLASH|REM expr",
+ /* 201 */ "expr ::= expr CONCAT expr",
+ /* 202 */ "likeop ::= NOT LIKE_KW|MATCH",
+ /* 203 */ "expr ::= expr likeop expr",
+ /* 204 */ "expr ::= expr likeop expr ESCAPE expr",
+ /* 205 */ "expr ::= expr ISNULL|NOTNULL",
+ /* 206 */ "expr ::= expr NOT NULL",
+ /* 207 */ "expr ::= expr IS expr",
+ /* 208 */ "expr ::= expr IS NOT expr",
+ /* 209 */ "expr ::= expr IS NOT DISTINCT FROM expr",
+ /* 210 */ "expr ::= expr IS DISTINCT FROM expr",
+ /* 211 */ "expr ::= NOT expr",
+ /* 212 */ "expr ::= BITNOT expr",
+ /* 213 */ "expr ::= PLUS|MINUS expr",
+ /* 214 */ "expr ::= expr PTR expr",
+ /* 215 */ "between_op ::= BETWEEN",
+ /* 216 */ "between_op ::= NOT BETWEEN",
+ /* 217 */ "expr ::= expr between_op expr AND expr",
+ /* 218 */ "in_op ::= IN",
+ /* 219 */ "in_op ::= NOT IN",
+ /* 220 */ "expr ::= expr in_op LP exprlist RP",
+ /* 221 */ "expr ::= LP select RP",
+ /* 222 */ "expr ::= expr in_op LP select RP",
+ /* 223 */ "expr ::= expr in_op nm dbnm paren_exprlist",
+ /* 224 */ "expr ::= EXISTS LP select RP",
+ /* 225 */ "expr ::= CASE case_operand case_exprlist case_else END",
+ /* 226 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr",
+ /* 227 */ "case_exprlist ::= WHEN expr THEN expr",
+ /* 228 */ "case_else ::= ELSE expr",
+ /* 229 */ "case_else ::=",
+ /* 230 */ "case_operand ::= expr",
+ /* 231 */ "case_operand ::=",
+ /* 232 */ "exprlist ::=",
+ /* 233 */ "nexprlist ::= nexprlist COMMA expr",
+ /* 234 */ "nexprlist ::= expr",
+ /* 235 */ "paren_exprlist ::=",
+ /* 236 */ "paren_exprlist ::= LP exprlist RP",
+ /* 237 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt",
+ /* 238 */ "uniqueflag ::= UNIQUE",
+ /* 239 */ "uniqueflag ::=",
+ /* 240 */ "eidlist_opt ::=",
+ /* 241 */ "eidlist_opt ::= LP eidlist RP",
+ /* 242 */ "eidlist ::= eidlist COMMA nm collate sortorder",
+ /* 243 */ "eidlist ::= nm collate sortorder",
+ /* 244 */ "collate ::=",
+ /* 245 */ "collate ::= COLLATE ID|STRING",
+ /* 246 */ "cmd ::= DROP INDEX ifexists fullname",
+ /* 247 */ "cmd ::= VACUUM vinto",
+ /* 248 */ "cmd ::= VACUUM nm vinto",
+ /* 249 */ "vinto ::= INTO expr",
+ /* 250 */ "vinto ::=",
+ /* 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 */ "plus_num ::= PLUS INTEGER|FLOAT",
+ /* 257 */ "minus_num ::= MINUS INTEGER|FLOAT",
+ /* 258 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END",
+ /* 259 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
+ /* 260 */ "trigger_time ::= BEFORE|AFTER",
+ /* 261 */ "trigger_time ::= INSTEAD OF",
+ /* 262 */ "trigger_time ::=",
+ /* 263 */ "trigger_event ::= DELETE|INSERT",
+ /* 264 */ "trigger_event ::= UPDATE",
+ /* 265 */ "trigger_event ::= UPDATE OF idlist",
+ /* 266 */ "when_clause ::=",
+ /* 267 */ "when_clause ::= WHEN expr",
+ /* 268 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI",
+ /* 269 */ "trigger_cmd_list ::= trigger_cmd SEMI",
+ /* 270 */ "trnm ::= nm DOT nm",
+ /* 271 */ "tridxby ::= INDEXED BY nm",
+ /* 272 */ "tridxby ::= NOT INDEXED",
+ /* 273 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt",
+ /* 274 */ "trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt",
+ /* 275 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt",
+ /* 276 */ "trigger_cmd ::= scanpt select scanpt",
+ /* 277 */ "expr ::= RAISE LP IGNORE RP",
+ /* 278 */ "expr ::= RAISE LP raisetype COMMA nm RP",
+ /* 279 */ "raisetype ::= ROLLBACK",
+ /* 280 */ "raisetype ::= ABORT",
+ /* 281 */ "raisetype ::= FAIL",
+ /* 282 */ "cmd ::= DROP TRIGGER ifexists fullname",
+ /* 283 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
+ /* 284 */ "cmd ::= DETACH database_kw_opt expr",
+ /* 285 */ "key_opt ::=",
+ /* 286 */ "key_opt ::= KEY expr",
+ /* 287 */ "cmd ::= REINDEX",
+ /* 288 */ "cmd ::= REINDEX nm dbnm",
+ /* 289 */ "cmd ::= ANALYZE",
+ /* 290 */ "cmd ::= ANALYZE nm dbnm",
+ /* 291 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
+ /* 292 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist",
+ /* 293 */ "cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm",
+ /* 294 */ "add_column_fullname ::= fullname",
+ /* 295 */ "cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm",
+ /* 296 */ "cmd ::= create_vtab",
+ /* 297 */ "cmd ::= create_vtab LP vtabarglist RP",
+ /* 298 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm",
+ /* 299 */ "vtabarg ::=",
+ /* 300 */ "vtabargtoken ::= ANY",
+ /* 301 */ "vtabargtoken ::= lp anylist RP",
+ /* 302 */ "lp ::= LP",
+ /* 303 */ "with ::= WITH wqlist",
+ /* 304 */ "with ::= WITH RECURSIVE wqlist",
+ /* 305 */ "wqas ::= AS",
+ /* 306 */ "wqas ::= AS MATERIALIZED",
+ /* 307 */ "wqas ::= AS NOT MATERIALIZED",
+ /* 308 */ "wqitem ::= nm eidlist_opt wqas LP select RP",
+ /* 309 */ "wqlist ::= wqitem",
+ /* 310 */ "wqlist ::= wqlist COMMA wqitem",
+ /* 311 */ "windowdefn_list ::= windowdefn",
+ /* 312 */ "windowdefn_list ::= windowdefn_list COMMA windowdefn",
+ /* 313 */ "windowdefn ::= nm AS LP window RP",
+ /* 314 */ "window ::= PARTITION BY nexprlist orderby_opt frame_opt",
+ /* 315 */ "window ::= nm PARTITION BY nexprlist orderby_opt frame_opt",
+ /* 316 */ "window ::= ORDER BY sortlist frame_opt",
+ /* 317 */ "window ::= nm ORDER BY sortlist frame_opt",
+ /* 318 */ "window ::= frame_opt",
+ /* 319 */ "window ::= nm frame_opt",
+ /* 320 */ "frame_opt ::=",
+ /* 321 */ "frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt",
+ /* 322 */ "frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt",
+ /* 323 */ "range_or_rows ::= RANGE|ROWS|GROUPS",
+ /* 324 */ "frame_bound_s ::= frame_bound",
+ /* 325 */ "frame_bound_s ::= UNBOUNDED PRECEDING",
+ /* 326 */ "frame_bound_e ::= frame_bound",
+ /* 327 */ "frame_bound_e ::= UNBOUNDED FOLLOWING",
+ /* 328 */ "frame_bound ::= expr PRECEDING|FOLLOWING",
+ /* 329 */ "frame_bound ::= CURRENT ROW",
+ /* 330 */ "frame_exclude_opt ::=",
+ /* 331 */ "frame_exclude_opt ::= EXCLUDE frame_exclude",
+ /* 332 */ "frame_exclude ::= NO OTHERS",
+ /* 333 */ "frame_exclude ::= CURRENT ROW",
+ /* 334 */ "frame_exclude ::= GROUP|TIES",
+ /* 335 */ "window_clause ::= WINDOW windowdefn_list",
+ /* 336 */ "filter_over ::= filter_clause over_clause",
+ /* 337 */ "filter_over ::= over_clause",
+ /* 338 */ "filter_over ::= filter_clause",
+ /* 339 */ "over_clause ::= OVER LP window RP",
+ /* 340 */ "over_clause ::= OVER nm",
+ /* 341 */ "filter_clause ::= FILTER LP WHERE expr RP",
+ /* 342 */ "input ::= cmdlist",
+ /* 343 */ "cmdlist ::= cmdlist ecmd",
+ /* 344 */ "cmdlist ::= ecmd",
+ /* 345 */ "ecmd ::= SEMI",
+ /* 346 */ "ecmd ::= cmdx SEMI",
+ /* 347 */ "ecmd ::= explain cmdx SEMI",
+ /* 348 */ "trans_opt ::=",
+ /* 349 */ "trans_opt ::= TRANSACTION",
+ /* 350 */ "trans_opt ::= TRANSACTION nm",
+ /* 351 */ "savepoint_opt ::= SAVEPOINT",
+ /* 352 */ "savepoint_opt ::=",
+ /* 353 */ "cmd ::= create_table create_table_args",
+ /* 354 */ "table_option_set ::= table_option",
+ /* 355 */ "columnlist ::= columnlist COMMA columnname carglist",
+ /* 356 */ "columnlist ::= columnname carglist",
+ /* 357 */ "nm ::= ID|INDEXED",
+ /* 358 */ "nm ::= STRING",
+ /* 359 */ "nm ::= JOIN_KW",
+ /* 360 */ "typetoken ::= typename",
+ /* 361 */ "typename ::= ID|STRING",
+ /* 362 */ "signed ::= plus_num",
+ /* 363 */ "signed ::= minus_num",
+ /* 364 */ "carglist ::= carglist ccons",
+ /* 365 */ "carglist ::=",
+ /* 366 */ "ccons ::= NULL onconf",
+ /* 367 */ "ccons ::= GENERATED ALWAYS AS generated",
+ /* 368 */ "ccons ::= AS generated",
+ /* 369 */ "conslist_opt ::= COMMA conslist",
+ /* 370 */ "conslist ::= conslist tconscomma tcons",
+ /* 371 */ "conslist ::= tcons",
+ /* 372 */ "tconscomma ::=",
+ /* 373 */ "defer_subclause_opt ::= defer_subclause",
+ /* 374 */ "resolvetype ::= raisetype",
+ /* 375 */ "selectnowith ::= oneselect",
+ /* 376 */ "oneselect ::= values",
+ /* 377 */ "sclp ::= selcollist COMMA",
+ /* 378 */ "as ::= ID|STRING",
+ /* 379 */ "indexed_opt ::= indexed_by",
+ /* 380 */ "returning ::=",
+ /* 381 */ "expr ::= term",
+ /* 382 */ "likeop ::= LIKE_KW|MATCH",
+ /* 383 */ "exprlist ::= nexprlist",
+ /* 384 */ "nmnum ::= plus_num",
+ /* 385 */ "nmnum ::= nm",
+ /* 386 */ "nmnum ::= ON",
+ /* 387 */ "nmnum ::= DELETE",
+ /* 388 */ "nmnum ::= DEFAULT",
+ /* 389 */ "plus_num ::= INTEGER|FLOAT",
+ /* 390 */ "foreach_clause ::=",
+ /* 391 */ "foreach_clause ::= FOR EACH ROW",
+ /* 392 */ "trnm ::= nm",
+ /* 393 */ "tridxby ::=",
+ /* 394 */ "database_kw_opt ::= DATABASE",
+ /* 395 */ "database_kw_opt ::=",
+ /* 396 */ "kwcolumn_opt ::=",
+ /* 397 */ "kwcolumn_opt ::= COLUMNKW",
+ /* 398 */ "vtabarglist ::= vtabarg",
+ /* 399 */ "vtabarglist ::= vtabarglist COMMA vtabarg",
+ /* 400 */ "vtabarg ::= vtabarg vtabargtoken",
+ /* 401 */ "anylist ::=",
+ /* 402 */ "anylist ::= anylist LP anylist RP",
+ /* 403 */ "anylist ::= anylist ANY",
+ /* 404 */ "with ::=",
};
#endif /* NDEBUG */
@@ -161980,98 +171232,97 @@ static void yy_destructor(
** inside the C code.
*/
/********* Begin destructor definitions ***************************************/
- case 200: /* select */
- case 234: /* selectnowith */
- case 235: /* oneselect */
- case 247: /* values */
+ case 204: /* select */
+ case 239: /* selectnowith */
+ case 240: /* oneselect */
+ case 252: /* values */
{
-sqlcipher_sqlite3SelectDelete(pParse->db, (yypminor->yy539));
-}
- break;
- case 211: /* term */
- case 212: /* expr */
- case 241: /* where_opt */
- case 243: /* having_opt */
- case 255: /* on_opt */
- case 271: /* case_operand */
- case 273: /* case_else */
- case 276: /* vinto */
- case 283: /* when_clause */
- case 288: /* key_opt */
- case 302: /* filter_clause */
+sqlcipher_sqlite3SelectDelete(pParse->db, (yypminor->yy47));
+}
+ break;
+ case 216: /* term */
+ case 217: /* expr */
+ case 246: /* where_opt */
+ case 248: /* having_opt */
+ case 267: /* where_opt_ret */
+ case 278: /* case_operand */
+ case 280: /* case_else */
+ case 283: /* vinto */
+ case 290: /* when_clause */
+ case 295: /* key_opt */
+ case 311: /* filter_clause */
{
-sqlcipher_sqlite3ExprDelete(pParse->db, (yypminor->yy202));
-}
- break;
- case 216: /* eidlist_opt */
- case 226: /* sortlist */
- case 227: /* eidlist */
- case 239: /* selcollist */
- case 242: /* groupby_opt */
- case 244: /* orderby_opt */
- case 248: /* nexprlist */
- case 249: /* sclp */
- case 257: /* exprlist */
- case 262: /* setlist */
- case 270: /* paren_exprlist */
- case 272: /* case_exprlist */
- case 301: /* part_opt */
+sqlcipher_sqlite3ExprDelete(pParse->db, (yypminor->yy528));
+}
+ break;
+ case 221: /* eidlist_opt */
+ case 231: /* sortlist */
+ case 232: /* eidlist */
+ case 244: /* selcollist */
+ case 247: /* groupby_opt */
+ case 249: /* orderby_opt */
+ case 253: /* nexprlist */
+ case 254: /* sclp */
+ case 261: /* exprlist */
+ case 268: /* setlist */
+ case 277: /* paren_exprlist */
+ case 279: /* case_exprlist */
+ case 310: /* part_opt */
{
-sqlcipher_sqlite3ExprListDelete(pParse->db, (yypminor->yy242));
+sqlcipher_sqlite3ExprListDelete(pParse->db, (yypminor->yy322));
}
break;
- case 233: /* fullname */
- case 240: /* from */
- case 251: /* seltablist */
- case 252: /* stl_prefix */
- case 258: /* xfullname */
+ case 238: /* fullname */
+ case 245: /* from */
+ case 256: /* seltablist */
+ case 257: /* stl_prefix */
+ case 262: /* xfullname */
{
-sqlcipher_sqlite3SrcListDelete(pParse->db, (yypminor->yy47));
+sqlcipher_sqlite3SrcListDelete(pParse->db, (yypminor->yy131));
}
break;
- case 236: /* wqlist */
+ case 241: /* wqlist */
{
-sqlcipher_sqlite3WithDelete(pParse->db, (yypminor->yy131));
+sqlcipher_sqlite3WithDelete(pParse->db, (yypminor->yy521));
}
break;
- case 246: /* window_clause */
- case 297: /* windowdefn_list */
+ case 251: /* window_clause */
+ case 306: /* windowdefn_list */
{
-sqlcipher_sqlite3WindowListDelete(pParse->db, (yypminor->yy303));
+sqlcipher_sqlite3WindowListDelete(pParse->db, (yypminor->yy41));
}
break;
- case 256: /* using_opt */
- case 259: /* idlist */
- case 264: /* idlist_opt */
+ case 263: /* idlist */
+ case 270: /* idlist_opt */
{
-sqlcipher_sqlite3IdListDelete(pParse->db, (yypminor->yy600));
+sqlcipher_sqlite3IdListDelete(pParse->db, (yypminor->yy254));
}
break;
- case 266: /* filter_over */
- case 298: /* windowdefn */
- case 299: /* window */
- case 300: /* frame_opt */
- case 303: /* over_clause */
+ case 273: /* filter_over */
+ case 307: /* windowdefn */
+ case 308: /* window */
+ case 309: /* frame_opt */
+ case 312: /* over_clause */
{
-sqlcipher_sqlite3WindowDelete(pParse->db, (yypminor->yy303));
+sqlcipher_sqlite3WindowDelete(pParse->db, (yypminor->yy41));
}
break;
- case 279: /* trigger_cmd_list */
- case 284: /* trigger_cmd */
+ case 286: /* trigger_cmd_list */
+ case 291: /* trigger_cmd */
{
-sqlcipher_sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy447));
+sqlcipher_sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy33));
}
break;
- case 281: /* trigger_event */
+ case 288: /* trigger_event */
{
-sqlcipher_sqlite3IdListDelete(pParse->db, (yypminor->yy230).b);
+sqlcipher_sqlite3IdListDelete(pParse->db, (yypminor->yy180).b);
}
break;
- case 305: /* frame_bound */
- case 306: /* frame_bound_s */
- case 307: /* frame_bound_e */
+ case 314: /* frame_bound */
+ case 315: /* frame_bound_s */
+ case 316: /* frame_bound_e */
{
-sqlcipher_sqlite3ExprDelete(pParse->db, (yypminor->yy77).pExpr);
+sqlcipher_sqlite3ExprDelete(pParse->db, (yypminor->yy595).pExpr);
}
break;
/********* End destructor definitions *****************************************/
@@ -162362,391 +171613,411 @@ static void yy_shift(
/* For rule J, yyRuleInfoLhs[J] contains the symbol on the left-hand side
** of that rule */
static const YYCODETYPE yyRuleInfoLhs[] = {
- 185, /* (0) explain ::= EXPLAIN */
- 185, /* (1) explain ::= EXPLAIN QUERY PLAN */
- 184, /* (2) cmdx ::= cmd */
- 186, /* (3) cmd ::= BEGIN transtype trans_opt */
- 187, /* (4) transtype ::= */
- 187, /* (5) transtype ::= DEFERRED */
- 187, /* (6) transtype ::= IMMEDIATE */
- 187, /* (7) transtype ::= EXCLUSIVE */
- 186, /* (8) cmd ::= COMMIT|END trans_opt */
- 186, /* (9) cmd ::= ROLLBACK trans_opt */
- 186, /* (10) cmd ::= SAVEPOINT nm */
- 186, /* (11) cmd ::= RELEASE savepoint_opt nm */
- 186, /* (12) cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */
- 191, /* (13) create_table ::= createkw temp TABLE ifnotexists nm dbnm */
- 193, /* (14) createkw ::= CREATE */
- 195, /* (15) ifnotexists ::= */
- 195, /* (16) ifnotexists ::= IF NOT EXISTS */
- 194, /* (17) temp ::= TEMP */
- 194, /* (18) temp ::= */
- 192, /* (19) create_table_args ::= LP columnlist conslist_opt RP table_options */
- 192, /* (20) create_table_args ::= AS select */
- 199, /* (21) table_options ::= */
- 199, /* (22) table_options ::= WITHOUT nm */
- 201, /* (23) columnname ::= nm typetoken */
- 203, /* (24) typetoken ::= */
- 203, /* (25) typetoken ::= typename LP signed RP */
- 203, /* (26) typetoken ::= typename LP signed COMMA signed RP */
- 204, /* (27) typename ::= typename ID|STRING */
- 208, /* (28) scanpt ::= */
- 209, /* (29) scantok ::= */
- 210, /* (30) ccons ::= CONSTRAINT nm */
- 210, /* (31) ccons ::= DEFAULT scantok term */
- 210, /* (32) ccons ::= DEFAULT LP expr RP */
- 210, /* (33) ccons ::= DEFAULT PLUS scantok term */
- 210, /* (34) ccons ::= DEFAULT MINUS scantok term */
- 210, /* (35) ccons ::= DEFAULT scantok ID|INDEXED */
- 210, /* (36) ccons ::= NOT NULL onconf */
- 210, /* (37) ccons ::= PRIMARY KEY sortorder onconf autoinc */
- 210, /* (38) ccons ::= UNIQUE onconf */
- 210, /* (39) ccons ::= CHECK LP expr RP */
- 210, /* (40) ccons ::= REFERENCES nm eidlist_opt refargs */
- 210, /* (41) ccons ::= defer_subclause */
- 210, /* (42) ccons ::= COLLATE ID|STRING */
- 219, /* (43) generated ::= LP expr RP */
- 219, /* (44) generated ::= LP expr RP ID */
- 215, /* (45) autoinc ::= */
- 215, /* (46) autoinc ::= AUTOINCR */
- 217, /* (47) refargs ::= */
- 217, /* (48) refargs ::= refargs refarg */
- 220, /* (49) refarg ::= MATCH nm */
- 220, /* (50) refarg ::= ON INSERT refact */
- 220, /* (51) refarg ::= ON DELETE refact */
- 220, /* (52) refarg ::= ON UPDATE refact */
- 221, /* (53) refact ::= SET NULL */
- 221, /* (54) refact ::= SET DEFAULT */
- 221, /* (55) refact ::= CASCADE */
- 221, /* (56) refact ::= RESTRICT */
- 221, /* (57) refact ::= NO ACTION */
- 218, /* (58) defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
- 218, /* (59) defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
- 222, /* (60) init_deferred_pred_opt ::= */
- 222, /* (61) init_deferred_pred_opt ::= INITIALLY DEFERRED */
- 222, /* (62) init_deferred_pred_opt ::= INITIALLY IMMEDIATE */
- 198, /* (63) conslist_opt ::= */
- 224, /* (64) tconscomma ::= COMMA */
- 225, /* (65) tcons ::= CONSTRAINT nm */
- 225, /* (66) tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */
- 225, /* (67) tcons ::= UNIQUE LP sortlist RP onconf */
- 225, /* (68) tcons ::= CHECK LP expr RP onconf */
- 225, /* (69) tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */
- 228, /* (70) defer_subclause_opt ::= */
- 213, /* (71) onconf ::= */
- 213, /* (72) onconf ::= ON CONFLICT resolvetype */
- 229, /* (73) orconf ::= */
- 229, /* (74) orconf ::= OR resolvetype */
- 230, /* (75) resolvetype ::= IGNORE */
- 230, /* (76) resolvetype ::= REPLACE */
- 186, /* (77) cmd ::= DROP TABLE ifexists fullname */
- 232, /* (78) ifexists ::= IF EXISTS */
- 232, /* (79) ifexists ::= */
- 186, /* (80) cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */
- 186, /* (81) cmd ::= DROP VIEW ifexists fullname */
- 186, /* (82) cmd ::= select */
- 200, /* (83) select ::= WITH wqlist selectnowith */
- 200, /* (84) select ::= WITH RECURSIVE wqlist selectnowith */
- 200, /* (85) select ::= selectnowith */
- 234, /* (86) selectnowith ::= selectnowith multiselect_op oneselect */
- 237, /* (87) multiselect_op ::= UNION */
- 237, /* (88) multiselect_op ::= UNION ALL */
- 237, /* (89) multiselect_op ::= EXCEPT|INTERSECT */
- 235, /* (90) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
- 235, /* (91) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */
- 247, /* (92) values ::= VALUES LP nexprlist RP */
- 247, /* (93) values ::= values COMMA LP nexprlist RP */
- 238, /* (94) distinct ::= DISTINCT */
- 238, /* (95) distinct ::= ALL */
- 238, /* (96) distinct ::= */
- 249, /* (97) sclp ::= */
- 239, /* (98) selcollist ::= sclp scanpt expr scanpt as */
- 239, /* (99) selcollist ::= sclp scanpt STAR */
- 239, /* (100) selcollist ::= sclp scanpt nm DOT STAR */
- 250, /* (101) as ::= AS nm */
- 250, /* (102) as ::= */
- 240, /* (103) from ::= */
- 240, /* (104) from ::= FROM seltablist */
- 252, /* (105) stl_prefix ::= seltablist joinop */
- 252, /* (106) stl_prefix ::= */
- 251, /* (107) seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
- 251, /* (108) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */
- 251, /* (109) seltablist ::= stl_prefix LP select RP as on_opt using_opt */
- 251, /* (110) seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
- 196, /* (111) dbnm ::= */
- 196, /* (112) dbnm ::= DOT nm */
- 233, /* (113) fullname ::= nm */
- 233, /* (114) fullname ::= nm DOT nm */
- 258, /* (115) xfullname ::= nm */
- 258, /* (116) xfullname ::= nm DOT nm */
- 258, /* (117) xfullname ::= nm DOT nm AS nm */
- 258, /* (118) xfullname ::= nm AS nm */
- 253, /* (119) joinop ::= COMMA|JOIN */
- 253, /* (120) joinop ::= JOIN_KW JOIN */
- 253, /* (121) joinop ::= JOIN_KW nm JOIN */
- 253, /* (122) joinop ::= JOIN_KW nm nm JOIN */
- 255, /* (123) on_opt ::= ON expr */
- 255, /* (124) on_opt ::= */
- 254, /* (125) indexed_opt ::= */
- 254, /* (126) indexed_opt ::= INDEXED BY nm */
- 254, /* (127) indexed_opt ::= NOT INDEXED */
- 256, /* (128) using_opt ::= USING LP idlist RP */
- 256, /* (129) using_opt ::= */
- 244, /* (130) orderby_opt ::= */
- 244, /* (131) orderby_opt ::= ORDER BY sortlist */
- 226, /* (132) sortlist ::= sortlist COMMA expr sortorder nulls */
- 226, /* (133) sortlist ::= expr sortorder nulls */
- 214, /* (134) sortorder ::= ASC */
- 214, /* (135) sortorder ::= DESC */
- 214, /* (136) sortorder ::= */
- 260, /* (137) nulls ::= NULLS FIRST */
- 260, /* (138) nulls ::= NULLS LAST */
- 260, /* (139) nulls ::= */
- 242, /* (140) groupby_opt ::= */
- 242, /* (141) groupby_opt ::= GROUP BY nexprlist */
- 243, /* (142) having_opt ::= */
- 243, /* (143) having_opt ::= HAVING expr */
- 245, /* (144) limit_opt ::= */
- 245, /* (145) limit_opt ::= LIMIT expr */
- 245, /* (146) limit_opt ::= LIMIT expr OFFSET expr */
- 245, /* (147) limit_opt ::= LIMIT expr COMMA expr */
- 186, /* (148) cmd ::= with DELETE FROM xfullname indexed_opt where_opt orderby_opt limit_opt */
- 241, /* (149) where_opt ::= */
- 241, /* (150) where_opt ::= WHERE expr */
- 186, /* (151) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt orderby_opt limit_opt */
- 262, /* (152) setlist ::= setlist COMMA nm EQ expr */
- 262, /* (153) setlist ::= setlist COMMA LP idlist RP EQ expr */
- 262, /* (154) setlist ::= nm EQ expr */
- 262, /* (155) setlist ::= LP idlist RP EQ expr */
- 186, /* (156) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */
- 186, /* (157) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES */
- 265, /* (158) upsert ::= */
- 265, /* (159) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt */
- 265, /* (160) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING */
- 265, /* (161) upsert ::= ON CONFLICT DO NOTHING */
- 263, /* (162) insert_cmd ::= INSERT orconf */
- 263, /* (163) insert_cmd ::= REPLACE */
- 264, /* (164) idlist_opt ::= */
- 264, /* (165) idlist_opt ::= LP idlist RP */
- 259, /* (166) idlist ::= idlist COMMA nm */
- 259, /* (167) idlist ::= nm */
- 212, /* (168) expr ::= LP expr RP */
- 212, /* (169) expr ::= ID|INDEXED */
- 212, /* (170) expr ::= JOIN_KW */
- 212, /* (171) expr ::= nm DOT nm */
- 212, /* (172) expr ::= nm DOT nm DOT nm */
- 211, /* (173) term ::= NULL|FLOAT|BLOB */
- 211, /* (174) term ::= STRING */
- 211, /* (175) term ::= INTEGER */
- 212, /* (176) expr ::= VARIABLE */
- 212, /* (177) expr ::= expr COLLATE ID|STRING */
- 212, /* (178) expr ::= CAST LP expr AS typetoken RP */
- 212, /* (179) expr ::= ID|INDEXED LP distinct exprlist RP */
- 212, /* (180) expr ::= ID|INDEXED LP STAR RP */
- 212, /* (181) expr ::= ID|INDEXED LP distinct exprlist RP filter_over */
- 212, /* (182) expr ::= ID|INDEXED LP STAR RP filter_over */
- 211, /* (183) term ::= CTIME_KW */
- 212, /* (184) expr ::= LP nexprlist COMMA expr RP */
- 212, /* (185) expr ::= expr AND expr */
- 212, /* (186) expr ::= expr OR expr */
- 212, /* (187) expr ::= expr LT|GT|GE|LE expr */
- 212, /* (188) expr ::= expr EQ|NE expr */
- 212, /* (189) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */
- 212, /* (190) expr ::= expr PLUS|MINUS expr */
- 212, /* (191) expr ::= expr STAR|SLASH|REM expr */
- 212, /* (192) expr ::= expr CONCAT expr */
- 267, /* (193) likeop ::= NOT LIKE_KW|MATCH */
- 212, /* (194) expr ::= expr likeop expr */
- 212, /* (195) expr ::= expr likeop expr ESCAPE expr */
- 212, /* (196) expr ::= expr ISNULL|NOTNULL */
- 212, /* (197) expr ::= expr NOT NULL */
- 212, /* (198) expr ::= expr IS expr */
- 212, /* (199) expr ::= expr IS NOT expr */
- 212, /* (200) expr ::= NOT expr */
- 212, /* (201) expr ::= BITNOT expr */
- 212, /* (202) expr ::= PLUS|MINUS expr */
- 268, /* (203) between_op ::= BETWEEN */
- 268, /* (204) between_op ::= NOT BETWEEN */
- 212, /* (205) expr ::= expr between_op expr AND expr */
- 269, /* (206) in_op ::= IN */
- 269, /* (207) in_op ::= NOT IN */
- 212, /* (208) expr ::= expr in_op LP exprlist RP */
- 212, /* (209) expr ::= LP select RP */
- 212, /* (210) expr ::= expr in_op LP select RP */
- 212, /* (211) expr ::= expr in_op nm dbnm paren_exprlist */
- 212, /* (212) expr ::= EXISTS LP select RP */
- 212, /* (213) expr ::= CASE case_operand case_exprlist case_else END */
- 272, /* (214) case_exprlist ::= case_exprlist WHEN expr THEN expr */
- 272, /* (215) case_exprlist ::= WHEN expr THEN expr */
- 273, /* (216) case_else ::= ELSE expr */
- 273, /* (217) case_else ::= */
- 271, /* (218) case_operand ::= expr */
- 271, /* (219) case_operand ::= */
- 257, /* (220) exprlist ::= */
- 248, /* (221) nexprlist ::= nexprlist COMMA expr */
- 248, /* (222) nexprlist ::= expr */
- 270, /* (223) paren_exprlist ::= */
- 270, /* (224) paren_exprlist ::= LP exprlist RP */
- 186, /* (225) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
- 274, /* (226) uniqueflag ::= UNIQUE */
- 274, /* (227) uniqueflag ::= */
- 216, /* (228) eidlist_opt ::= */
- 216, /* (229) eidlist_opt ::= LP eidlist RP */
- 227, /* (230) eidlist ::= eidlist COMMA nm collate sortorder */
- 227, /* (231) eidlist ::= nm collate sortorder */
- 275, /* (232) collate ::= */
- 275, /* (233) collate ::= COLLATE ID|STRING */
- 186, /* (234) cmd ::= DROP INDEX ifexists fullname */
- 186, /* (235) cmd ::= VACUUM vinto */
- 186, /* (236) cmd ::= VACUUM nm vinto */
- 276, /* (237) vinto ::= INTO expr */
- 276, /* (238) vinto ::= */
- 186, /* (239) cmd ::= PRAGMA nm dbnm */
- 186, /* (240) cmd ::= PRAGMA nm dbnm EQ nmnum */
- 186, /* (241) cmd ::= PRAGMA nm dbnm LP nmnum RP */
- 186, /* (242) cmd ::= PRAGMA nm dbnm EQ minus_num */
- 186, /* (243) cmd ::= PRAGMA nm dbnm LP minus_num RP */
- 206, /* (244) plus_num ::= PLUS INTEGER|FLOAT */
- 207, /* (245) minus_num ::= MINUS INTEGER|FLOAT */
- 186, /* (246) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
- 278, /* (247) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
- 280, /* (248) trigger_time ::= BEFORE|AFTER */
- 280, /* (249) trigger_time ::= INSTEAD OF */
- 280, /* (250) trigger_time ::= */
- 281, /* (251) trigger_event ::= DELETE|INSERT */
- 281, /* (252) trigger_event ::= UPDATE */
- 281, /* (253) trigger_event ::= UPDATE OF idlist */
- 283, /* (254) when_clause ::= */
- 283, /* (255) when_clause ::= WHEN expr */
- 279, /* (256) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
- 279, /* (257) trigger_cmd_list ::= trigger_cmd SEMI */
- 285, /* (258) trnm ::= nm DOT nm */
- 286, /* (259) tridxby ::= INDEXED BY nm */
- 286, /* (260) tridxby ::= NOT INDEXED */
- 284, /* (261) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */
- 284, /* (262) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
- 284, /* (263) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
- 284, /* (264) trigger_cmd ::= scanpt select scanpt */
- 212, /* (265) expr ::= RAISE LP IGNORE RP */
- 212, /* (266) expr ::= RAISE LP raisetype COMMA nm RP */
- 231, /* (267) raisetype ::= ROLLBACK */
- 231, /* (268) raisetype ::= ABORT */
- 231, /* (269) raisetype ::= FAIL */
- 186, /* (270) cmd ::= DROP TRIGGER ifexists fullname */
- 186, /* (271) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
- 186, /* (272) cmd ::= DETACH database_kw_opt expr */
- 288, /* (273) key_opt ::= */
- 288, /* (274) key_opt ::= KEY expr */
- 186, /* (275) cmd ::= REINDEX */
- 186, /* (276) cmd ::= REINDEX nm dbnm */
- 186, /* (277) cmd ::= ANALYZE */
- 186, /* (278) cmd ::= ANALYZE nm dbnm */
- 186, /* (279) cmd ::= ALTER TABLE fullname RENAME TO nm */
- 186, /* (280) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
- 289, /* (281) add_column_fullname ::= fullname */
- 186, /* (282) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
- 186, /* (283) cmd ::= create_vtab */
- 186, /* (284) cmd ::= create_vtab LP vtabarglist RP */
- 291, /* (285) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
- 293, /* (286) vtabarg ::= */
- 294, /* (287) vtabargtoken ::= ANY */
- 294, /* (288) vtabargtoken ::= lp anylist RP */
- 295, /* (289) lp ::= LP */
- 261, /* (290) with ::= WITH wqlist */
- 261, /* (291) with ::= WITH RECURSIVE wqlist */
- 236, /* (292) wqlist ::= nm eidlist_opt AS LP select RP */
- 236, /* (293) wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */
- 297, /* (294) windowdefn_list ::= windowdefn */
- 297, /* (295) windowdefn_list ::= windowdefn_list COMMA windowdefn */
- 298, /* (296) windowdefn ::= nm AS LP window RP */
- 299, /* (297) window ::= PARTITION BY nexprlist orderby_opt frame_opt */
- 299, /* (298) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */
- 299, /* (299) window ::= ORDER BY sortlist frame_opt */
- 299, /* (300) window ::= nm ORDER BY sortlist frame_opt */
- 299, /* (301) window ::= frame_opt */
- 299, /* (302) window ::= nm frame_opt */
- 300, /* (303) frame_opt ::= */
- 300, /* (304) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */
- 300, /* (305) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */
- 304, /* (306) range_or_rows ::= RANGE|ROWS|GROUPS */
- 306, /* (307) frame_bound_s ::= frame_bound */
- 306, /* (308) frame_bound_s ::= UNBOUNDED PRECEDING */
- 307, /* (309) frame_bound_e ::= frame_bound */
- 307, /* (310) frame_bound_e ::= UNBOUNDED FOLLOWING */
- 305, /* (311) frame_bound ::= expr PRECEDING|FOLLOWING */
- 305, /* (312) frame_bound ::= CURRENT ROW */
- 308, /* (313) frame_exclude_opt ::= */
- 308, /* (314) frame_exclude_opt ::= EXCLUDE frame_exclude */
- 309, /* (315) frame_exclude ::= NO OTHERS */
- 309, /* (316) frame_exclude ::= CURRENT ROW */
- 309, /* (317) frame_exclude ::= GROUP|TIES */
- 246, /* (318) window_clause ::= WINDOW windowdefn_list */
- 266, /* (319) filter_over ::= filter_clause over_clause */
- 266, /* (320) filter_over ::= over_clause */
- 266, /* (321) filter_over ::= filter_clause */
- 303, /* (322) over_clause ::= OVER LP window RP */
- 303, /* (323) over_clause ::= OVER nm */
- 302, /* (324) filter_clause ::= FILTER LP WHERE expr RP */
- 181, /* (325) input ::= cmdlist */
- 182, /* (326) cmdlist ::= cmdlist ecmd */
- 182, /* (327) cmdlist ::= ecmd */
- 183, /* (328) ecmd ::= SEMI */
- 183, /* (329) ecmd ::= cmdx SEMI */
- 183, /* (330) ecmd ::= explain cmdx SEMI */
- 188, /* (331) trans_opt ::= */
- 188, /* (332) trans_opt ::= TRANSACTION */
- 188, /* (333) trans_opt ::= TRANSACTION nm */
- 190, /* (334) savepoint_opt ::= SAVEPOINT */
- 190, /* (335) savepoint_opt ::= */
- 186, /* (336) cmd ::= create_table create_table_args */
- 197, /* (337) columnlist ::= columnlist COMMA columnname carglist */
- 197, /* (338) columnlist ::= columnname carglist */
- 189, /* (339) nm ::= ID|INDEXED */
- 189, /* (340) nm ::= STRING */
- 189, /* (341) nm ::= JOIN_KW */
- 203, /* (342) typetoken ::= typename */
- 204, /* (343) typename ::= ID|STRING */
- 205, /* (344) signed ::= plus_num */
- 205, /* (345) signed ::= minus_num */
- 202, /* (346) carglist ::= carglist ccons */
- 202, /* (347) carglist ::= */
- 210, /* (348) ccons ::= NULL onconf */
- 210, /* (349) ccons ::= GENERATED ALWAYS AS generated */
- 210, /* (350) ccons ::= AS generated */
- 198, /* (351) conslist_opt ::= COMMA conslist */
- 223, /* (352) conslist ::= conslist tconscomma tcons */
- 223, /* (353) conslist ::= tcons */
- 224, /* (354) tconscomma ::= */
- 228, /* (355) defer_subclause_opt ::= defer_subclause */
- 230, /* (356) resolvetype ::= raisetype */
- 234, /* (357) selectnowith ::= oneselect */
- 235, /* (358) oneselect ::= values */
- 249, /* (359) sclp ::= selcollist COMMA */
- 250, /* (360) as ::= ID|STRING */
- 212, /* (361) expr ::= term */
- 267, /* (362) likeop ::= LIKE_KW|MATCH */
- 257, /* (363) exprlist ::= nexprlist */
- 277, /* (364) nmnum ::= plus_num */
- 277, /* (365) nmnum ::= nm */
- 277, /* (366) nmnum ::= ON */
- 277, /* (367) nmnum ::= DELETE */
- 277, /* (368) nmnum ::= DEFAULT */
- 206, /* (369) plus_num ::= INTEGER|FLOAT */
- 282, /* (370) foreach_clause ::= */
- 282, /* (371) foreach_clause ::= FOR EACH ROW */
- 285, /* (372) trnm ::= nm */
- 286, /* (373) tridxby ::= */
- 287, /* (374) database_kw_opt ::= DATABASE */
- 287, /* (375) database_kw_opt ::= */
- 290, /* (376) kwcolumn_opt ::= */
- 290, /* (377) kwcolumn_opt ::= COLUMNKW */
- 292, /* (378) vtabarglist ::= vtabarg */
- 292, /* (379) vtabarglist ::= vtabarglist COMMA vtabarg */
- 293, /* (380) vtabarg ::= vtabarg vtabargtoken */
- 296, /* (381) anylist ::= */
- 296, /* (382) anylist ::= anylist LP anylist RP */
- 296, /* (383) anylist ::= anylist ANY */
- 261, /* (384) with ::= */
+ 189, /* (0) explain ::= EXPLAIN */
+ 189, /* (1) explain ::= EXPLAIN QUERY PLAN */
+ 188, /* (2) cmdx ::= cmd */
+ 190, /* (3) cmd ::= BEGIN transtype trans_opt */
+ 191, /* (4) transtype ::= */
+ 191, /* (5) transtype ::= DEFERRED */
+ 191, /* (6) transtype ::= IMMEDIATE */
+ 191, /* (7) transtype ::= EXCLUSIVE */
+ 190, /* (8) cmd ::= COMMIT|END trans_opt */
+ 190, /* (9) cmd ::= ROLLBACK trans_opt */
+ 190, /* (10) cmd ::= SAVEPOINT nm */
+ 190, /* (11) cmd ::= RELEASE savepoint_opt nm */
+ 190, /* (12) cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */
+ 195, /* (13) create_table ::= createkw temp TABLE ifnotexists nm dbnm */
+ 197, /* (14) createkw ::= CREATE */
+ 199, /* (15) ifnotexists ::= */
+ 199, /* (16) ifnotexists ::= IF NOT EXISTS */
+ 198, /* (17) temp ::= TEMP */
+ 198, /* (18) temp ::= */
+ 196, /* (19) create_table_args ::= LP columnlist conslist_opt RP table_option_set */
+ 196, /* (20) create_table_args ::= AS select */
+ 203, /* (21) table_option_set ::= */
+ 203, /* (22) table_option_set ::= table_option_set COMMA table_option */
+ 205, /* (23) table_option ::= WITHOUT nm */
+ 205, /* (24) table_option ::= nm */
+ 206, /* (25) columnname ::= nm typetoken */
+ 208, /* (26) typetoken ::= */
+ 208, /* (27) typetoken ::= typename LP signed RP */
+ 208, /* (28) typetoken ::= typename LP signed COMMA signed RP */
+ 209, /* (29) typename ::= typename ID|STRING */
+ 213, /* (30) scanpt ::= */
+ 214, /* (31) scantok ::= */
+ 215, /* (32) ccons ::= CONSTRAINT nm */
+ 215, /* (33) ccons ::= DEFAULT scantok term */
+ 215, /* (34) ccons ::= DEFAULT LP expr RP */
+ 215, /* (35) ccons ::= DEFAULT PLUS scantok term */
+ 215, /* (36) ccons ::= DEFAULT MINUS scantok term */
+ 215, /* (37) ccons ::= DEFAULT scantok ID|INDEXED */
+ 215, /* (38) ccons ::= NOT NULL onconf */
+ 215, /* (39) ccons ::= PRIMARY KEY sortorder onconf autoinc */
+ 215, /* (40) ccons ::= UNIQUE onconf */
+ 215, /* (41) ccons ::= CHECK LP expr RP */
+ 215, /* (42) ccons ::= REFERENCES nm eidlist_opt refargs */
+ 215, /* (43) ccons ::= defer_subclause */
+ 215, /* (44) ccons ::= COLLATE ID|STRING */
+ 224, /* (45) generated ::= LP expr RP */
+ 224, /* (46) generated ::= LP expr RP ID */
+ 220, /* (47) autoinc ::= */
+ 220, /* (48) autoinc ::= AUTOINCR */
+ 222, /* (49) refargs ::= */
+ 222, /* (50) refargs ::= refargs refarg */
+ 225, /* (51) refarg ::= MATCH nm */
+ 225, /* (52) refarg ::= ON INSERT refact */
+ 225, /* (53) refarg ::= ON DELETE refact */
+ 225, /* (54) refarg ::= ON UPDATE refact */
+ 226, /* (55) refact ::= SET NULL */
+ 226, /* (56) refact ::= SET DEFAULT */
+ 226, /* (57) refact ::= CASCADE */
+ 226, /* (58) refact ::= RESTRICT */
+ 226, /* (59) refact ::= NO ACTION */
+ 223, /* (60) defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
+ 223, /* (61) defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
+ 227, /* (62) init_deferred_pred_opt ::= */
+ 227, /* (63) init_deferred_pred_opt ::= INITIALLY DEFERRED */
+ 227, /* (64) init_deferred_pred_opt ::= INITIALLY IMMEDIATE */
+ 202, /* (65) conslist_opt ::= */
+ 229, /* (66) tconscomma ::= COMMA */
+ 230, /* (67) tcons ::= CONSTRAINT nm */
+ 230, /* (68) tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */
+ 230, /* (69) tcons ::= UNIQUE LP sortlist RP onconf */
+ 230, /* (70) tcons ::= CHECK LP expr RP onconf */
+ 230, /* (71) tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */
+ 233, /* (72) defer_subclause_opt ::= */
+ 218, /* (73) onconf ::= */
+ 218, /* (74) onconf ::= ON CONFLICT resolvetype */
+ 234, /* (75) orconf ::= */
+ 234, /* (76) orconf ::= OR resolvetype */
+ 235, /* (77) resolvetype ::= IGNORE */
+ 235, /* (78) resolvetype ::= REPLACE */
+ 190, /* (79) cmd ::= DROP TABLE ifexists fullname */
+ 237, /* (80) ifexists ::= IF EXISTS */
+ 237, /* (81) ifexists ::= */
+ 190, /* (82) cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */
+ 190, /* (83) cmd ::= DROP VIEW ifexists fullname */
+ 190, /* (84) cmd ::= select */
+ 204, /* (85) select ::= WITH wqlist selectnowith */
+ 204, /* (86) select ::= WITH RECURSIVE wqlist selectnowith */
+ 204, /* (87) select ::= selectnowith */
+ 239, /* (88) selectnowith ::= selectnowith multiselect_op oneselect */
+ 242, /* (89) multiselect_op ::= UNION */
+ 242, /* (90) multiselect_op ::= UNION ALL */
+ 242, /* (91) multiselect_op ::= EXCEPT|INTERSECT */
+ 240, /* (92) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
+ 240, /* (93) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */
+ 252, /* (94) values ::= VALUES LP nexprlist RP */
+ 252, /* (95) values ::= values COMMA LP nexprlist RP */
+ 243, /* (96) distinct ::= DISTINCT */
+ 243, /* (97) distinct ::= ALL */
+ 243, /* (98) distinct ::= */
+ 254, /* (99) sclp ::= */
+ 244, /* (100) selcollist ::= sclp scanpt expr scanpt as */
+ 244, /* (101) selcollist ::= sclp scanpt STAR */
+ 244, /* (102) selcollist ::= sclp scanpt nm DOT STAR */
+ 255, /* (103) as ::= AS nm */
+ 255, /* (104) as ::= */
+ 245, /* (105) from ::= */
+ 245, /* (106) from ::= FROM seltablist */
+ 257, /* (107) stl_prefix ::= seltablist joinop */
+ 257, /* (108) stl_prefix ::= */
+ 256, /* (109) seltablist ::= stl_prefix nm dbnm as on_using */
+ 256, /* (110) seltablist ::= stl_prefix nm dbnm as indexed_by on_using */
+ 256, /* (111) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using */
+ 256, /* (112) seltablist ::= stl_prefix LP select RP as on_using */
+ 256, /* (113) seltablist ::= stl_prefix LP seltablist RP as on_using */
+ 200, /* (114) dbnm ::= */
+ 200, /* (115) dbnm ::= DOT nm */
+ 238, /* (116) fullname ::= nm */
+ 238, /* (117) fullname ::= nm DOT nm */
+ 262, /* (118) xfullname ::= nm */
+ 262, /* (119) xfullname ::= nm DOT nm */
+ 262, /* (120) xfullname ::= nm DOT nm AS nm */
+ 262, /* (121) xfullname ::= nm AS nm */
+ 258, /* (122) joinop ::= COMMA|JOIN */
+ 258, /* (123) joinop ::= JOIN_KW JOIN */
+ 258, /* (124) joinop ::= JOIN_KW nm JOIN */
+ 258, /* (125) joinop ::= JOIN_KW nm nm JOIN */
+ 259, /* (126) on_using ::= ON expr */
+ 259, /* (127) on_using ::= USING LP idlist RP */
+ 259, /* (128) on_using ::= */
+ 264, /* (129) indexed_opt ::= */
+ 260, /* (130) indexed_by ::= INDEXED BY nm */
+ 260, /* (131) indexed_by ::= NOT INDEXED */
+ 249, /* (132) orderby_opt ::= */
+ 249, /* (133) orderby_opt ::= ORDER BY sortlist */
+ 231, /* (134) sortlist ::= sortlist COMMA expr sortorder nulls */
+ 231, /* (135) sortlist ::= expr sortorder nulls */
+ 219, /* (136) sortorder ::= ASC */
+ 219, /* (137) sortorder ::= DESC */
+ 219, /* (138) sortorder ::= */
+ 265, /* (139) nulls ::= NULLS FIRST */
+ 265, /* (140) nulls ::= NULLS LAST */
+ 265, /* (141) nulls ::= */
+ 247, /* (142) groupby_opt ::= */
+ 247, /* (143) groupby_opt ::= GROUP BY nexprlist */
+ 248, /* (144) having_opt ::= */
+ 248, /* (145) having_opt ::= HAVING expr */
+ 250, /* (146) limit_opt ::= */
+ 250, /* (147) limit_opt ::= LIMIT expr */
+ 250, /* (148) limit_opt ::= LIMIT expr OFFSET expr */
+ 250, /* (149) limit_opt ::= LIMIT expr COMMA expr */
+ 190, /* (150) cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret orderby_opt limit_opt */
+ 246, /* (151) where_opt ::= */
+ 246, /* (152) where_opt ::= WHERE expr */
+ 267, /* (153) where_opt_ret ::= */
+ 267, /* (154) where_opt_ret ::= WHERE expr */
+ 267, /* (155) where_opt_ret ::= RETURNING selcollist */
+ 267, /* (156) where_opt_ret ::= WHERE expr RETURNING selcollist */
+ 190, /* (157) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret orderby_opt limit_opt */
+ 268, /* (158) setlist ::= setlist COMMA nm EQ expr */
+ 268, /* (159) setlist ::= setlist COMMA LP idlist RP EQ expr */
+ 268, /* (160) setlist ::= nm EQ expr */
+ 268, /* (161) setlist ::= LP idlist RP EQ expr */
+ 190, /* (162) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */
+ 190, /* (163) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning */
+ 271, /* (164) upsert ::= */
+ 271, /* (165) upsert ::= RETURNING selcollist */
+ 271, /* (166) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert */
+ 271, /* (167) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert */
+ 271, /* (168) upsert ::= ON CONFLICT DO NOTHING returning */
+ 271, /* (169) upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning */
+ 272, /* (170) returning ::= RETURNING selcollist */
+ 269, /* (171) insert_cmd ::= INSERT orconf */
+ 269, /* (172) insert_cmd ::= REPLACE */
+ 270, /* (173) idlist_opt ::= */
+ 270, /* (174) idlist_opt ::= LP idlist RP */
+ 263, /* (175) idlist ::= idlist COMMA nm */
+ 263, /* (176) idlist ::= nm */
+ 217, /* (177) expr ::= LP expr RP */
+ 217, /* (178) expr ::= ID|INDEXED */
+ 217, /* (179) expr ::= JOIN_KW */
+ 217, /* (180) expr ::= nm DOT nm */
+ 217, /* (181) expr ::= nm DOT nm DOT nm */
+ 216, /* (182) term ::= NULL|FLOAT|BLOB */
+ 216, /* (183) term ::= STRING */
+ 216, /* (184) term ::= INTEGER */
+ 217, /* (185) expr ::= VARIABLE */
+ 217, /* (186) expr ::= expr COLLATE ID|STRING */
+ 217, /* (187) expr ::= CAST LP expr AS typetoken RP */
+ 217, /* (188) expr ::= ID|INDEXED LP distinct exprlist RP */
+ 217, /* (189) expr ::= ID|INDEXED LP STAR RP */
+ 217, /* (190) expr ::= ID|INDEXED LP distinct exprlist RP filter_over */
+ 217, /* (191) expr ::= ID|INDEXED LP STAR RP filter_over */
+ 216, /* (192) term ::= CTIME_KW */
+ 217, /* (193) expr ::= LP nexprlist COMMA expr RP */
+ 217, /* (194) expr ::= expr AND expr */
+ 217, /* (195) expr ::= expr OR expr */
+ 217, /* (196) expr ::= expr LT|GT|GE|LE expr */
+ 217, /* (197) expr ::= expr EQ|NE expr */
+ 217, /* (198) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */
+ 217, /* (199) expr ::= expr PLUS|MINUS expr */
+ 217, /* (200) expr ::= expr STAR|SLASH|REM expr */
+ 217, /* (201) expr ::= expr CONCAT expr */
+ 274, /* (202) likeop ::= NOT LIKE_KW|MATCH */
+ 217, /* (203) expr ::= expr likeop expr */
+ 217, /* (204) expr ::= expr likeop expr ESCAPE expr */
+ 217, /* (205) expr ::= expr ISNULL|NOTNULL */
+ 217, /* (206) expr ::= expr NOT NULL */
+ 217, /* (207) expr ::= expr IS expr */
+ 217, /* (208) expr ::= expr IS NOT expr */
+ 217, /* (209) expr ::= expr IS NOT DISTINCT FROM expr */
+ 217, /* (210) expr ::= expr IS DISTINCT FROM expr */
+ 217, /* (211) expr ::= NOT expr */
+ 217, /* (212) expr ::= BITNOT expr */
+ 217, /* (213) expr ::= PLUS|MINUS expr */
+ 217, /* (214) expr ::= expr PTR expr */
+ 275, /* (215) between_op ::= BETWEEN */
+ 275, /* (216) between_op ::= NOT BETWEEN */
+ 217, /* (217) expr ::= expr between_op expr AND expr */
+ 276, /* (218) in_op ::= IN */
+ 276, /* (219) in_op ::= NOT IN */
+ 217, /* (220) expr ::= expr in_op LP exprlist RP */
+ 217, /* (221) expr ::= LP select RP */
+ 217, /* (222) expr ::= expr in_op LP select RP */
+ 217, /* (223) expr ::= expr in_op nm dbnm paren_exprlist */
+ 217, /* (224) expr ::= EXISTS LP select RP */
+ 217, /* (225) expr ::= CASE case_operand case_exprlist case_else END */
+ 279, /* (226) case_exprlist ::= case_exprlist WHEN expr THEN expr */
+ 279, /* (227) case_exprlist ::= WHEN expr THEN expr */
+ 280, /* (228) case_else ::= ELSE expr */
+ 280, /* (229) case_else ::= */
+ 278, /* (230) case_operand ::= expr */
+ 278, /* (231) case_operand ::= */
+ 261, /* (232) exprlist ::= */
+ 253, /* (233) nexprlist ::= nexprlist COMMA expr */
+ 253, /* (234) nexprlist ::= expr */
+ 277, /* (235) paren_exprlist ::= */
+ 277, /* (236) paren_exprlist ::= LP exprlist RP */
+ 190, /* (237) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
+ 281, /* (238) uniqueflag ::= UNIQUE */
+ 281, /* (239) uniqueflag ::= */
+ 221, /* (240) eidlist_opt ::= */
+ 221, /* (241) eidlist_opt ::= LP eidlist RP */
+ 232, /* (242) eidlist ::= eidlist COMMA nm collate sortorder */
+ 232, /* (243) eidlist ::= nm collate sortorder */
+ 282, /* (244) collate ::= */
+ 282, /* (245) collate ::= COLLATE ID|STRING */
+ 190, /* (246) cmd ::= DROP INDEX ifexists fullname */
+ 190, /* (247) cmd ::= VACUUM vinto */
+ 190, /* (248) cmd ::= VACUUM nm vinto */
+ 283, /* (249) vinto ::= INTO expr */
+ 283, /* (250) vinto ::= */
+ 190, /* (251) cmd ::= PRAGMA nm dbnm */
+ 190, /* (252) cmd ::= PRAGMA nm dbnm EQ nmnum */
+ 190, /* (253) cmd ::= PRAGMA nm dbnm LP nmnum RP */
+ 190, /* (254) cmd ::= PRAGMA nm dbnm EQ minus_num */
+ 190, /* (255) cmd ::= PRAGMA nm dbnm LP minus_num RP */
+ 211, /* (256) plus_num ::= PLUS INTEGER|FLOAT */
+ 212, /* (257) minus_num ::= MINUS INTEGER|FLOAT */
+ 190, /* (258) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
+ 285, /* (259) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
+ 287, /* (260) trigger_time ::= BEFORE|AFTER */
+ 287, /* (261) trigger_time ::= INSTEAD OF */
+ 287, /* (262) trigger_time ::= */
+ 288, /* (263) trigger_event ::= DELETE|INSERT */
+ 288, /* (264) trigger_event ::= UPDATE */
+ 288, /* (265) trigger_event ::= UPDATE OF idlist */
+ 290, /* (266) when_clause ::= */
+ 290, /* (267) when_clause ::= WHEN expr */
+ 286, /* (268) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
+ 286, /* (269) trigger_cmd_list ::= trigger_cmd SEMI */
+ 292, /* (270) trnm ::= nm DOT nm */
+ 293, /* (271) tridxby ::= INDEXED BY nm */
+ 293, /* (272) tridxby ::= NOT INDEXED */
+ 291, /* (273) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */
+ 291, /* (274) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
+ 291, /* (275) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
+ 291, /* (276) trigger_cmd ::= scanpt select scanpt */
+ 217, /* (277) expr ::= RAISE LP IGNORE RP */
+ 217, /* (278) expr ::= RAISE LP raisetype COMMA nm RP */
+ 236, /* (279) raisetype ::= ROLLBACK */
+ 236, /* (280) raisetype ::= ABORT */
+ 236, /* (281) raisetype ::= FAIL */
+ 190, /* (282) cmd ::= DROP TRIGGER ifexists fullname */
+ 190, /* (283) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
+ 190, /* (284) cmd ::= DETACH database_kw_opt expr */
+ 295, /* (285) key_opt ::= */
+ 295, /* (286) key_opt ::= KEY expr */
+ 190, /* (287) cmd ::= REINDEX */
+ 190, /* (288) cmd ::= REINDEX nm dbnm */
+ 190, /* (289) cmd ::= ANALYZE */
+ 190, /* (290) cmd ::= ANALYZE nm dbnm */
+ 190, /* (291) cmd ::= ALTER TABLE fullname RENAME TO nm */
+ 190, /* (292) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
+ 190, /* (293) cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */
+ 296, /* (294) add_column_fullname ::= fullname */
+ 190, /* (295) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
+ 190, /* (296) cmd ::= create_vtab */
+ 190, /* (297) cmd ::= create_vtab LP vtabarglist RP */
+ 298, /* (298) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
+ 300, /* (299) vtabarg ::= */
+ 301, /* (300) vtabargtoken ::= ANY */
+ 301, /* (301) vtabargtoken ::= lp anylist RP */
+ 302, /* (302) lp ::= LP */
+ 266, /* (303) with ::= WITH wqlist */
+ 266, /* (304) with ::= WITH RECURSIVE wqlist */
+ 305, /* (305) wqas ::= AS */
+ 305, /* (306) wqas ::= AS MATERIALIZED */
+ 305, /* (307) wqas ::= AS NOT MATERIALIZED */
+ 304, /* (308) wqitem ::= nm eidlist_opt wqas LP select RP */
+ 241, /* (309) wqlist ::= wqitem */
+ 241, /* (310) wqlist ::= wqlist COMMA wqitem */
+ 306, /* (311) windowdefn_list ::= windowdefn */
+ 306, /* (312) windowdefn_list ::= windowdefn_list COMMA windowdefn */
+ 307, /* (313) windowdefn ::= nm AS LP window RP */
+ 308, /* (314) window ::= PARTITION BY nexprlist orderby_opt frame_opt */
+ 308, /* (315) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */
+ 308, /* (316) window ::= ORDER BY sortlist frame_opt */
+ 308, /* (317) window ::= nm ORDER BY sortlist frame_opt */
+ 308, /* (318) window ::= frame_opt */
+ 308, /* (319) window ::= nm frame_opt */
+ 309, /* (320) frame_opt ::= */
+ 309, /* (321) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */
+ 309, /* (322) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */
+ 313, /* (323) range_or_rows ::= RANGE|ROWS|GROUPS */
+ 315, /* (324) frame_bound_s ::= frame_bound */
+ 315, /* (325) frame_bound_s ::= UNBOUNDED PRECEDING */
+ 316, /* (326) frame_bound_e ::= frame_bound */
+ 316, /* (327) frame_bound_e ::= UNBOUNDED FOLLOWING */
+ 314, /* (328) frame_bound ::= expr PRECEDING|FOLLOWING */
+ 314, /* (329) frame_bound ::= CURRENT ROW */
+ 317, /* (330) frame_exclude_opt ::= */
+ 317, /* (331) frame_exclude_opt ::= EXCLUDE frame_exclude */
+ 318, /* (332) frame_exclude ::= NO OTHERS */
+ 318, /* (333) frame_exclude ::= CURRENT ROW */
+ 318, /* (334) frame_exclude ::= GROUP|TIES */
+ 251, /* (335) window_clause ::= WINDOW windowdefn_list */
+ 273, /* (336) filter_over ::= filter_clause over_clause */
+ 273, /* (337) filter_over ::= over_clause */
+ 273, /* (338) filter_over ::= filter_clause */
+ 312, /* (339) over_clause ::= OVER LP window RP */
+ 312, /* (340) over_clause ::= OVER nm */
+ 311, /* (341) filter_clause ::= FILTER LP WHERE expr RP */
+ 185, /* (342) input ::= cmdlist */
+ 186, /* (343) cmdlist ::= cmdlist ecmd */
+ 186, /* (344) cmdlist ::= ecmd */
+ 187, /* (345) ecmd ::= SEMI */
+ 187, /* (346) ecmd ::= cmdx SEMI */
+ 187, /* (347) ecmd ::= explain cmdx SEMI */
+ 192, /* (348) trans_opt ::= */
+ 192, /* (349) trans_opt ::= TRANSACTION */
+ 192, /* (350) trans_opt ::= TRANSACTION nm */
+ 194, /* (351) savepoint_opt ::= SAVEPOINT */
+ 194, /* (352) savepoint_opt ::= */
+ 190, /* (353) cmd ::= create_table create_table_args */
+ 203, /* (354) table_option_set ::= table_option */
+ 201, /* (355) columnlist ::= columnlist COMMA columnname carglist */
+ 201, /* (356) columnlist ::= columnname carglist */
+ 193, /* (357) nm ::= ID|INDEXED */
+ 193, /* (358) nm ::= STRING */
+ 193, /* (359) nm ::= JOIN_KW */
+ 208, /* (360) typetoken ::= typename */
+ 209, /* (361) typename ::= ID|STRING */
+ 210, /* (362) signed ::= plus_num */
+ 210, /* (363) signed ::= minus_num */
+ 207, /* (364) carglist ::= carglist ccons */
+ 207, /* (365) carglist ::= */
+ 215, /* (366) ccons ::= NULL onconf */
+ 215, /* (367) ccons ::= GENERATED ALWAYS AS generated */
+ 215, /* (368) ccons ::= AS generated */
+ 202, /* (369) conslist_opt ::= COMMA conslist */
+ 228, /* (370) conslist ::= conslist tconscomma tcons */
+ 228, /* (371) conslist ::= tcons */
+ 229, /* (372) tconscomma ::= */
+ 233, /* (373) defer_subclause_opt ::= defer_subclause */
+ 235, /* (374) resolvetype ::= raisetype */
+ 239, /* (375) selectnowith ::= oneselect */
+ 240, /* (376) oneselect ::= values */
+ 254, /* (377) sclp ::= selcollist COMMA */
+ 255, /* (378) as ::= ID|STRING */
+ 264, /* (379) indexed_opt ::= indexed_by */
+ 272, /* (380) returning ::= */
+ 217, /* (381) expr ::= term */
+ 274, /* (382) likeop ::= LIKE_KW|MATCH */
+ 261, /* (383) exprlist ::= nexprlist */
+ 284, /* (384) nmnum ::= plus_num */
+ 284, /* (385) nmnum ::= nm */
+ 284, /* (386) nmnum ::= ON */
+ 284, /* (387) nmnum ::= DELETE */
+ 284, /* (388) nmnum ::= DEFAULT */
+ 211, /* (389) plus_num ::= INTEGER|FLOAT */
+ 289, /* (390) foreach_clause ::= */
+ 289, /* (391) foreach_clause ::= FOR EACH ROW */
+ 292, /* (392) trnm ::= nm */
+ 293, /* (393) tridxby ::= */
+ 294, /* (394) database_kw_opt ::= DATABASE */
+ 294, /* (395) database_kw_opt ::= */
+ 297, /* (396) kwcolumn_opt ::= */
+ 297, /* (397) kwcolumn_opt ::= COLUMNKW */
+ 299, /* (398) vtabarglist ::= vtabarg */
+ 299, /* (399) vtabarglist ::= vtabarglist COMMA vtabarg */
+ 300, /* (400) vtabarg ::= vtabarg vtabargtoken */
+ 303, /* (401) anylist ::= */
+ 303, /* (402) anylist ::= anylist LP anylist RP */
+ 303, /* (403) anylist ::= anylist ANY */
+ 266, /* (404) with ::= */
};
/* For rule J, yyRuleInfoNRhs[J] contains the negative of the number
@@ -162771,372 +172042,392 @@ static const signed char yyRuleInfoNRhs[] = {
-3, /* (16) ifnotexists ::= IF NOT EXISTS */
-1, /* (17) temp ::= TEMP */
0, /* (18) temp ::= */
- -5, /* (19) create_table_args ::= LP columnlist conslist_opt RP table_options */
+ -5, /* (19) create_table_args ::= LP columnlist conslist_opt RP table_option_set */
-2, /* (20) create_table_args ::= AS select */
- 0, /* (21) table_options ::= */
- -2, /* (22) table_options ::= WITHOUT nm */
- -2, /* (23) columnname ::= nm typetoken */
- 0, /* (24) typetoken ::= */
- -4, /* (25) typetoken ::= typename LP signed RP */
- -6, /* (26) typetoken ::= typename LP signed COMMA signed RP */
- -2, /* (27) typename ::= typename ID|STRING */
- 0, /* (28) scanpt ::= */
- 0, /* (29) scantok ::= */
- -2, /* (30) ccons ::= CONSTRAINT nm */
- -3, /* (31) ccons ::= DEFAULT scantok term */
- -4, /* (32) ccons ::= DEFAULT LP expr RP */
- -4, /* (33) ccons ::= DEFAULT PLUS scantok term */
- -4, /* (34) ccons ::= DEFAULT MINUS scantok term */
- -3, /* (35) ccons ::= DEFAULT scantok ID|INDEXED */
- -3, /* (36) ccons ::= NOT NULL onconf */
- -5, /* (37) ccons ::= PRIMARY KEY sortorder onconf autoinc */
- -2, /* (38) ccons ::= UNIQUE onconf */
- -4, /* (39) ccons ::= CHECK LP expr RP */
- -4, /* (40) ccons ::= REFERENCES nm eidlist_opt refargs */
- -1, /* (41) ccons ::= defer_subclause */
- -2, /* (42) ccons ::= COLLATE ID|STRING */
- -3, /* (43) generated ::= LP expr RP */
- -4, /* (44) generated ::= LP expr RP ID */
- 0, /* (45) autoinc ::= */
- -1, /* (46) autoinc ::= AUTOINCR */
- 0, /* (47) refargs ::= */
- -2, /* (48) refargs ::= refargs refarg */
- -2, /* (49) refarg ::= MATCH nm */
- -3, /* (50) refarg ::= ON INSERT refact */
- -3, /* (51) refarg ::= ON DELETE refact */
- -3, /* (52) refarg ::= ON UPDATE refact */
- -2, /* (53) refact ::= SET NULL */
- -2, /* (54) refact ::= SET DEFAULT */
- -1, /* (55) refact ::= CASCADE */
- -1, /* (56) refact ::= RESTRICT */
- -2, /* (57) refact ::= NO ACTION */
- -3, /* (58) defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
- -2, /* (59) defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
- 0, /* (60) init_deferred_pred_opt ::= */
- -2, /* (61) init_deferred_pred_opt ::= INITIALLY DEFERRED */
- -2, /* (62) init_deferred_pred_opt ::= INITIALLY IMMEDIATE */
- 0, /* (63) conslist_opt ::= */
- -1, /* (64) tconscomma ::= COMMA */
- -2, /* (65) tcons ::= CONSTRAINT nm */
- -7, /* (66) tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */
- -5, /* (67) tcons ::= UNIQUE LP sortlist RP onconf */
- -5, /* (68) tcons ::= CHECK LP expr RP onconf */
- -10, /* (69) tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */
- 0, /* (70) defer_subclause_opt ::= */
- 0, /* (71) onconf ::= */
- -3, /* (72) onconf ::= ON CONFLICT resolvetype */
- 0, /* (73) orconf ::= */
- -2, /* (74) orconf ::= OR resolvetype */
- -1, /* (75) resolvetype ::= IGNORE */
- -1, /* (76) resolvetype ::= REPLACE */
- -4, /* (77) cmd ::= DROP TABLE ifexists fullname */
- -2, /* (78) ifexists ::= IF EXISTS */
- 0, /* (79) ifexists ::= */
- -9, /* (80) cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */
- -4, /* (81) cmd ::= DROP VIEW ifexists fullname */
- -1, /* (82) cmd ::= select */
- -3, /* (83) select ::= WITH wqlist selectnowith */
- -4, /* (84) select ::= WITH RECURSIVE wqlist selectnowith */
- -1, /* (85) select ::= selectnowith */
- -3, /* (86) selectnowith ::= selectnowith multiselect_op oneselect */
- -1, /* (87) multiselect_op ::= UNION */
- -2, /* (88) multiselect_op ::= UNION ALL */
- -1, /* (89) multiselect_op ::= EXCEPT|INTERSECT */
- -9, /* (90) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
- -10, /* (91) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */
- -4, /* (92) values ::= VALUES LP nexprlist RP */
- -5, /* (93) values ::= values COMMA LP nexprlist RP */
- -1, /* (94) distinct ::= DISTINCT */
- -1, /* (95) distinct ::= ALL */
- 0, /* (96) distinct ::= */
- 0, /* (97) sclp ::= */
- -5, /* (98) selcollist ::= sclp scanpt expr scanpt as */
- -3, /* (99) selcollist ::= sclp scanpt STAR */
- -5, /* (100) selcollist ::= sclp scanpt nm DOT STAR */
- -2, /* (101) as ::= AS nm */
- 0, /* (102) as ::= */
- 0, /* (103) from ::= */
- -2, /* (104) from ::= FROM seltablist */
- -2, /* (105) stl_prefix ::= seltablist joinop */
- 0, /* (106) stl_prefix ::= */
- -7, /* (107) seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
- -9, /* (108) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */
- -7, /* (109) seltablist ::= stl_prefix LP select RP as on_opt using_opt */
- -7, /* (110) seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
- 0, /* (111) dbnm ::= */
- -2, /* (112) dbnm ::= DOT nm */
- -1, /* (113) fullname ::= nm */
- -3, /* (114) fullname ::= nm DOT nm */
- -1, /* (115) xfullname ::= nm */
- -3, /* (116) xfullname ::= nm DOT nm */
- -5, /* (117) xfullname ::= nm DOT nm AS nm */
- -3, /* (118) xfullname ::= nm AS nm */
- -1, /* (119) joinop ::= COMMA|JOIN */
- -2, /* (120) joinop ::= JOIN_KW JOIN */
- -3, /* (121) joinop ::= JOIN_KW nm JOIN */
- -4, /* (122) joinop ::= JOIN_KW nm nm JOIN */
- -2, /* (123) on_opt ::= ON expr */
- 0, /* (124) on_opt ::= */
- 0, /* (125) indexed_opt ::= */
- -3, /* (126) indexed_opt ::= INDEXED BY nm */
- -2, /* (127) indexed_opt ::= NOT INDEXED */
- -4, /* (128) using_opt ::= USING LP idlist RP */
- 0, /* (129) using_opt ::= */
- 0, /* (130) orderby_opt ::= */
- -3, /* (131) orderby_opt ::= ORDER BY sortlist */
- -5, /* (132) sortlist ::= sortlist COMMA expr sortorder nulls */
- -3, /* (133) sortlist ::= expr sortorder nulls */
- -1, /* (134) sortorder ::= ASC */
- -1, /* (135) sortorder ::= DESC */
- 0, /* (136) sortorder ::= */
- -2, /* (137) nulls ::= NULLS FIRST */
- -2, /* (138) nulls ::= NULLS LAST */
- 0, /* (139) nulls ::= */
- 0, /* (140) groupby_opt ::= */
- -3, /* (141) groupby_opt ::= GROUP BY nexprlist */
- 0, /* (142) having_opt ::= */
- -2, /* (143) having_opt ::= HAVING expr */
- 0, /* (144) limit_opt ::= */
- -2, /* (145) limit_opt ::= LIMIT expr */
- -4, /* (146) limit_opt ::= LIMIT expr OFFSET expr */
- -4, /* (147) limit_opt ::= LIMIT expr COMMA expr */
- -8, /* (148) cmd ::= with DELETE FROM xfullname indexed_opt where_opt orderby_opt limit_opt */
- 0, /* (149) where_opt ::= */
- -2, /* (150) where_opt ::= WHERE expr */
- -11, /* (151) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt orderby_opt limit_opt */
- -5, /* (152) setlist ::= setlist COMMA nm EQ expr */
- -7, /* (153) setlist ::= setlist COMMA LP idlist RP EQ expr */
- -3, /* (154) setlist ::= nm EQ expr */
- -5, /* (155) setlist ::= LP idlist RP EQ expr */
- -7, /* (156) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */
- -7, /* (157) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES */
- 0, /* (158) upsert ::= */
- -11, /* (159) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt */
- -8, /* (160) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING */
- -4, /* (161) upsert ::= ON CONFLICT DO NOTHING */
- -2, /* (162) insert_cmd ::= INSERT orconf */
- -1, /* (163) insert_cmd ::= REPLACE */
- 0, /* (164) idlist_opt ::= */
- -3, /* (165) idlist_opt ::= LP idlist RP */
- -3, /* (166) idlist ::= idlist COMMA nm */
- -1, /* (167) idlist ::= nm */
- -3, /* (168) expr ::= LP expr RP */
- -1, /* (169) expr ::= ID|INDEXED */
- -1, /* (170) expr ::= JOIN_KW */
- -3, /* (171) expr ::= nm DOT nm */
- -5, /* (172) expr ::= nm DOT nm DOT nm */
- -1, /* (173) term ::= NULL|FLOAT|BLOB */
- -1, /* (174) term ::= STRING */
- -1, /* (175) term ::= INTEGER */
- -1, /* (176) expr ::= VARIABLE */
- -3, /* (177) expr ::= expr COLLATE ID|STRING */
- -6, /* (178) expr ::= CAST LP expr AS typetoken RP */
- -5, /* (179) expr ::= ID|INDEXED LP distinct exprlist RP */
- -4, /* (180) expr ::= ID|INDEXED LP STAR RP */
- -6, /* (181) expr ::= ID|INDEXED LP distinct exprlist RP filter_over */
- -5, /* (182) expr ::= ID|INDEXED LP STAR RP filter_over */
- -1, /* (183) term ::= CTIME_KW */
- -5, /* (184) expr ::= LP nexprlist COMMA expr RP */
- -3, /* (185) expr ::= expr AND expr */
- -3, /* (186) expr ::= expr OR expr */
- -3, /* (187) expr ::= expr LT|GT|GE|LE expr */
- -3, /* (188) expr ::= expr EQ|NE expr */
- -3, /* (189) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */
- -3, /* (190) expr ::= expr PLUS|MINUS expr */
- -3, /* (191) expr ::= expr STAR|SLASH|REM expr */
- -3, /* (192) expr ::= expr CONCAT expr */
- -2, /* (193) likeop ::= NOT LIKE_KW|MATCH */
- -3, /* (194) expr ::= expr likeop expr */
- -5, /* (195) expr ::= expr likeop expr ESCAPE expr */
- -2, /* (196) expr ::= expr ISNULL|NOTNULL */
- -3, /* (197) expr ::= expr NOT NULL */
- -3, /* (198) expr ::= expr IS expr */
- -4, /* (199) expr ::= expr IS NOT expr */
- -2, /* (200) expr ::= NOT expr */
- -2, /* (201) expr ::= BITNOT expr */
- -2, /* (202) expr ::= PLUS|MINUS expr */
- -1, /* (203) between_op ::= BETWEEN */
- -2, /* (204) between_op ::= NOT BETWEEN */
- -5, /* (205) expr ::= expr between_op expr AND expr */
- -1, /* (206) in_op ::= IN */
- -2, /* (207) in_op ::= NOT IN */
- -5, /* (208) expr ::= expr in_op LP exprlist RP */
- -3, /* (209) expr ::= LP select RP */
- -5, /* (210) expr ::= expr in_op LP select RP */
- -5, /* (211) expr ::= expr in_op nm dbnm paren_exprlist */
- -4, /* (212) expr ::= EXISTS LP select RP */
- -5, /* (213) expr ::= CASE case_operand case_exprlist case_else END */
- -5, /* (214) case_exprlist ::= case_exprlist WHEN expr THEN expr */
- -4, /* (215) case_exprlist ::= WHEN expr THEN expr */
- -2, /* (216) case_else ::= ELSE expr */
- 0, /* (217) case_else ::= */
- -1, /* (218) case_operand ::= expr */
- 0, /* (219) case_operand ::= */
- 0, /* (220) exprlist ::= */
- -3, /* (221) nexprlist ::= nexprlist COMMA expr */
- -1, /* (222) nexprlist ::= expr */
- 0, /* (223) paren_exprlist ::= */
- -3, /* (224) paren_exprlist ::= LP exprlist RP */
- -12, /* (225) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
- -1, /* (226) uniqueflag ::= UNIQUE */
- 0, /* (227) uniqueflag ::= */
- 0, /* (228) eidlist_opt ::= */
- -3, /* (229) eidlist_opt ::= LP eidlist RP */
- -5, /* (230) eidlist ::= eidlist COMMA nm collate sortorder */
- -3, /* (231) eidlist ::= nm collate sortorder */
- 0, /* (232) collate ::= */
- -2, /* (233) collate ::= COLLATE ID|STRING */
- -4, /* (234) cmd ::= DROP INDEX ifexists fullname */
- -2, /* (235) cmd ::= VACUUM vinto */
- -3, /* (236) cmd ::= VACUUM nm vinto */
- -2, /* (237) vinto ::= INTO expr */
- 0, /* (238) vinto ::= */
- -3, /* (239) cmd ::= PRAGMA nm dbnm */
- -5, /* (240) cmd ::= PRAGMA nm dbnm EQ nmnum */
- -6, /* (241) cmd ::= PRAGMA nm dbnm LP nmnum RP */
- -5, /* (242) cmd ::= PRAGMA nm dbnm EQ minus_num */
- -6, /* (243) cmd ::= PRAGMA nm dbnm LP minus_num RP */
- -2, /* (244) plus_num ::= PLUS INTEGER|FLOAT */
- -2, /* (245) minus_num ::= MINUS INTEGER|FLOAT */
- -5, /* (246) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
- -11, /* (247) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
- -1, /* (248) trigger_time ::= BEFORE|AFTER */
- -2, /* (249) trigger_time ::= INSTEAD OF */
- 0, /* (250) trigger_time ::= */
- -1, /* (251) trigger_event ::= DELETE|INSERT */
- -1, /* (252) trigger_event ::= UPDATE */
- -3, /* (253) trigger_event ::= UPDATE OF idlist */
- 0, /* (254) when_clause ::= */
- -2, /* (255) when_clause ::= WHEN expr */
- -3, /* (256) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
- -2, /* (257) trigger_cmd_list ::= trigger_cmd SEMI */
- -3, /* (258) trnm ::= nm DOT nm */
- -3, /* (259) tridxby ::= INDEXED BY nm */
- -2, /* (260) tridxby ::= NOT INDEXED */
- -9, /* (261) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */
- -8, /* (262) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
- -6, /* (263) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
- -3, /* (264) trigger_cmd ::= scanpt select scanpt */
- -4, /* (265) expr ::= RAISE LP IGNORE RP */
- -6, /* (266) expr ::= RAISE LP raisetype COMMA nm RP */
- -1, /* (267) raisetype ::= ROLLBACK */
- -1, /* (268) raisetype ::= ABORT */
- -1, /* (269) raisetype ::= FAIL */
- -4, /* (270) cmd ::= DROP TRIGGER ifexists fullname */
- -6, /* (271) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
- -3, /* (272) cmd ::= DETACH database_kw_opt expr */
- 0, /* (273) key_opt ::= */
- -2, /* (274) key_opt ::= KEY expr */
- -1, /* (275) cmd ::= REINDEX */
- -3, /* (276) cmd ::= REINDEX nm dbnm */
- -1, /* (277) cmd ::= ANALYZE */
- -3, /* (278) cmd ::= ANALYZE nm dbnm */
- -6, /* (279) cmd ::= ALTER TABLE fullname RENAME TO nm */
- -7, /* (280) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
- -1, /* (281) add_column_fullname ::= fullname */
- -8, /* (282) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
- -1, /* (283) cmd ::= create_vtab */
- -4, /* (284) cmd ::= create_vtab LP vtabarglist RP */
- -8, /* (285) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
- 0, /* (286) vtabarg ::= */
- -1, /* (287) vtabargtoken ::= ANY */
- -3, /* (288) vtabargtoken ::= lp anylist RP */
- -1, /* (289) lp ::= LP */
- -2, /* (290) with ::= WITH wqlist */
- -3, /* (291) with ::= WITH RECURSIVE wqlist */
- -6, /* (292) wqlist ::= nm eidlist_opt AS LP select RP */
- -8, /* (293) wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */
- -1, /* (294) windowdefn_list ::= windowdefn */
- -3, /* (295) windowdefn_list ::= windowdefn_list COMMA windowdefn */
- -5, /* (296) windowdefn ::= nm AS LP window RP */
- -5, /* (297) window ::= PARTITION BY nexprlist orderby_opt frame_opt */
- -6, /* (298) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */
- -4, /* (299) window ::= ORDER BY sortlist frame_opt */
- -5, /* (300) window ::= nm ORDER BY sortlist frame_opt */
- -1, /* (301) window ::= frame_opt */
- -2, /* (302) window ::= nm frame_opt */
- 0, /* (303) frame_opt ::= */
- -3, /* (304) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */
- -6, /* (305) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */
- -1, /* (306) range_or_rows ::= RANGE|ROWS|GROUPS */
- -1, /* (307) frame_bound_s ::= frame_bound */
- -2, /* (308) frame_bound_s ::= UNBOUNDED PRECEDING */
- -1, /* (309) frame_bound_e ::= frame_bound */
- -2, /* (310) frame_bound_e ::= UNBOUNDED FOLLOWING */
- -2, /* (311) frame_bound ::= expr PRECEDING|FOLLOWING */
- -2, /* (312) frame_bound ::= CURRENT ROW */
- 0, /* (313) frame_exclude_opt ::= */
- -2, /* (314) frame_exclude_opt ::= EXCLUDE frame_exclude */
- -2, /* (315) frame_exclude ::= NO OTHERS */
- -2, /* (316) frame_exclude ::= CURRENT ROW */
- -1, /* (317) frame_exclude ::= GROUP|TIES */
- -2, /* (318) window_clause ::= WINDOW windowdefn_list */
- -2, /* (319) filter_over ::= filter_clause over_clause */
- -1, /* (320) filter_over ::= over_clause */
- -1, /* (321) filter_over ::= filter_clause */
- -4, /* (322) over_clause ::= OVER LP window RP */
- -2, /* (323) over_clause ::= OVER nm */
- -5, /* (324) filter_clause ::= FILTER LP WHERE expr RP */
- -1, /* (325) input ::= cmdlist */
- -2, /* (326) cmdlist ::= cmdlist ecmd */
- -1, /* (327) cmdlist ::= ecmd */
- -1, /* (328) ecmd ::= SEMI */
- -2, /* (329) ecmd ::= cmdx SEMI */
- -3, /* (330) ecmd ::= explain cmdx SEMI */
- 0, /* (331) trans_opt ::= */
- -1, /* (332) trans_opt ::= TRANSACTION */
- -2, /* (333) trans_opt ::= TRANSACTION nm */
- -1, /* (334) savepoint_opt ::= SAVEPOINT */
- 0, /* (335) savepoint_opt ::= */
- -2, /* (336) cmd ::= create_table create_table_args */
- -4, /* (337) columnlist ::= columnlist COMMA columnname carglist */
- -2, /* (338) columnlist ::= columnname carglist */
- -1, /* (339) nm ::= ID|INDEXED */
- -1, /* (340) nm ::= STRING */
- -1, /* (341) nm ::= JOIN_KW */
- -1, /* (342) typetoken ::= typename */
- -1, /* (343) typename ::= ID|STRING */
- -1, /* (344) signed ::= plus_num */
- -1, /* (345) signed ::= minus_num */
- -2, /* (346) carglist ::= carglist ccons */
- 0, /* (347) carglist ::= */
- -2, /* (348) ccons ::= NULL onconf */
- -4, /* (349) ccons ::= GENERATED ALWAYS AS generated */
- -2, /* (350) ccons ::= AS generated */
- -2, /* (351) conslist_opt ::= COMMA conslist */
- -3, /* (352) conslist ::= conslist tconscomma tcons */
- -1, /* (353) conslist ::= tcons */
- 0, /* (354) tconscomma ::= */
- -1, /* (355) defer_subclause_opt ::= defer_subclause */
- -1, /* (356) resolvetype ::= raisetype */
- -1, /* (357) selectnowith ::= oneselect */
- -1, /* (358) oneselect ::= values */
- -2, /* (359) sclp ::= selcollist COMMA */
- -1, /* (360) as ::= ID|STRING */
- -1, /* (361) expr ::= term */
- -1, /* (362) likeop ::= LIKE_KW|MATCH */
- -1, /* (363) exprlist ::= nexprlist */
- -1, /* (364) nmnum ::= plus_num */
- -1, /* (365) nmnum ::= nm */
- -1, /* (366) nmnum ::= ON */
- -1, /* (367) nmnum ::= DELETE */
- -1, /* (368) nmnum ::= DEFAULT */
- -1, /* (369) plus_num ::= INTEGER|FLOAT */
- 0, /* (370) foreach_clause ::= */
- -3, /* (371) foreach_clause ::= FOR EACH ROW */
- -1, /* (372) trnm ::= nm */
- 0, /* (373) tridxby ::= */
- -1, /* (374) database_kw_opt ::= DATABASE */
- 0, /* (375) database_kw_opt ::= */
- 0, /* (376) kwcolumn_opt ::= */
- -1, /* (377) kwcolumn_opt ::= COLUMNKW */
- -1, /* (378) vtabarglist ::= vtabarg */
- -3, /* (379) vtabarglist ::= vtabarglist COMMA vtabarg */
- -2, /* (380) vtabarg ::= vtabarg vtabargtoken */
- 0, /* (381) anylist ::= */
- -4, /* (382) anylist ::= anylist LP anylist RP */
- -2, /* (383) anylist ::= anylist ANY */
- 0, /* (384) with ::= */
+ 0, /* (21) table_option_set ::= */
+ -3, /* (22) table_option_set ::= table_option_set COMMA table_option */
+ -2, /* (23) table_option ::= WITHOUT nm */
+ -1, /* (24) table_option ::= nm */
+ -2, /* (25) columnname ::= nm typetoken */
+ 0, /* (26) typetoken ::= */
+ -4, /* (27) typetoken ::= typename LP signed RP */
+ -6, /* (28) typetoken ::= typename LP signed COMMA signed RP */
+ -2, /* (29) typename ::= typename ID|STRING */
+ 0, /* (30) scanpt ::= */
+ 0, /* (31) scantok ::= */
+ -2, /* (32) ccons ::= CONSTRAINT nm */
+ -3, /* (33) ccons ::= DEFAULT scantok term */
+ -4, /* (34) ccons ::= DEFAULT LP expr RP */
+ -4, /* (35) ccons ::= DEFAULT PLUS scantok term */
+ -4, /* (36) ccons ::= DEFAULT MINUS scantok term */
+ -3, /* (37) ccons ::= DEFAULT scantok ID|INDEXED */
+ -3, /* (38) ccons ::= NOT NULL onconf */
+ -5, /* (39) ccons ::= PRIMARY KEY sortorder onconf autoinc */
+ -2, /* (40) ccons ::= UNIQUE onconf */
+ -4, /* (41) ccons ::= CHECK LP expr RP */
+ -4, /* (42) ccons ::= REFERENCES nm eidlist_opt refargs */
+ -1, /* (43) ccons ::= defer_subclause */
+ -2, /* (44) ccons ::= COLLATE ID|STRING */
+ -3, /* (45) generated ::= LP expr RP */
+ -4, /* (46) generated ::= LP expr RP ID */
+ 0, /* (47) autoinc ::= */
+ -1, /* (48) autoinc ::= AUTOINCR */
+ 0, /* (49) refargs ::= */
+ -2, /* (50) refargs ::= refargs refarg */
+ -2, /* (51) refarg ::= MATCH nm */
+ -3, /* (52) refarg ::= ON INSERT refact */
+ -3, /* (53) refarg ::= ON DELETE refact */
+ -3, /* (54) refarg ::= ON UPDATE refact */
+ -2, /* (55) refact ::= SET NULL */
+ -2, /* (56) refact ::= SET DEFAULT */
+ -1, /* (57) refact ::= CASCADE */
+ -1, /* (58) refact ::= RESTRICT */
+ -2, /* (59) refact ::= NO ACTION */
+ -3, /* (60) defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
+ -2, /* (61) defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
+ 0, /* (62) init_deferred_pred_opt ::= */
+ -2, /* (63) init_deferred_pred_opt ::= INITIALLY DEFERRED */
+ -2, /* (64) init_deferred_pred_opt ::= INITIALLY IMMEDIATE */
+ 0, /* (65) conslist_opt ::= */
+ -1, /* (66) tconscomma ::= COMMA */
+ -2, /* (67) tcons ::= CONSTRAINT nm */
+ -7, /* (68) tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */
+ -5, /* (69) tcons ::= UNIQUE LP sortlist RP onconf */
+ -5, /* (70) tcons ::= CHECK LP expr RP onconf */
+ -10, /* (71) tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */
+ 0, /* (72) defer_subclause_opt ::= */
+ 0, /* (73) onconf ::= */
+ -3, /* (74) onconf ::= ON CONFLICT resolvetype */
+ 0, /* (75) orconf ::= */
+ -2, /* (76) orconf ::= OR resolvetype */
+ -1, /* (77) resolvetype ::= IGNORE */
+ -1, /* (78) resolvetype ::= REPLACE */
+ -4, /* (79) cmd ::= DROP TABLE ifexists fullname */
+ -2, /* (80) ifexists ::= IF EXISTS */
+ 0, /* (81) ifexists ::= */
+ -9, /* (82) cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */
+ -4, /* (83) cmd ::= DROP VIEW ifexists fullname */
+ -1, /* (84) cmd ::= select */
+ -3, /* (85) select ::= WITH wqlist selectnowith */
+ -4, /* (86) select ::= WITH RECURSIVE wqlist selectnowith */
+ -1, /* (87) select ::= selectnowith */
+ -3, /* (88) selectnowith ::= selectnowith multiselect_op oneselect */
+ -1, /* (89) multiselect_op ::= UNION */
+ -2, /* (90) multiselect_op ::= UNION ALL */
+ -1, /* (91) multiselect_op ::= EXCEPT|INTERSECT */
+ -9, /* (92) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
+ -10, /* (93) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */
+ -4, /* (94) values ::= VALUES LP nexprlist RP */
+ -5, /* (95) values ::= values COMMA LP nexprlist RP */
+ -1, /* (96) distinct ::= DISTINCT */
+ -1, /* (97) distinct ::= ALL */
+ 0, /* (98) distinct ::= */
+ 0, /* (99) sclp ::= */
+ -5, /* (100) selcollist ::= sclp scanpt expr scanpt as */
+ -3, /* (101) selcollist ::= sclp scanpt STAR */
+ -5, /* (102) selcollist ::= sclp scanpt nm DOT STAR */
+ -2, /* (103) as ::= AS nm */
+ 0, /* (104) as ::= */
+ 0, /* (105) from ::= */
+ -2, /* (106) from ::= FROM seltablist */
+ -2, /* (107) stl_prefix ::= seltablist joinop */
+ 0, /* (108) stl_prefix ::= */
+ -5, /* (109) seltablist ::= stl_prefix nm dbnm as on_using */
+ -6, /* (110) seltablist ::= stl_prefix nm dbnm as indexed_by on_using */
+ -8, /* (111) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using */
+ -6, /* (112) seltablist ::= stl_prefix LP select RP as on_using */
+ -6, /* (113) seltablist ::= stl_prefix LP seltablist RP as on_using */
+ 0, /* (114) dbnm ::= */
+ -2, /* (115) dbnm ::= DOT nm */
+ -1, /* (116) fullname ::= nm */
+ -3, /* (117) fullname ::= nm DOT nm */
+ -1, /* (118) xfullname ::= nm */
+ -3, /* (119) xfullname ::= nm DOT nm */
+ -5, /* (120) xfullname ::= nm DOT nm AS nm */
+ -3, /* (121) xfullname ::= nm AS nm */
+ -1, /* (122) joinop ::= COMMA|JOIN */
+ -2, /* (123) joinop ::= JOIN_KW JOIN */
+ -3, /* (124) joinop ::= JOIN_KW nm JOIN */
+ -4, /* (125) joinop ::= JOIN_KW nm nm JOIN */
+ -2, /* (126) on_using ::= ON expr */
+ -4, /* (127) on_using ::= USING LP idlist RP */
+ 0, /* (128) on_using ::= */
+ 0, /* (129) indexed_opt ::= */
+ -3, /* (130) indexed_by ::= INDEXED BY nm */
+ -2, /* (131) indexed_by ::= NOT INDEXED */
+ 0, /* (132) orderby_opt ::= */
+ -3, /* (133) orderby_opt ::= ORDER BY sortlist */
+ -5, /* (134) sortlist ::= sortlist COMMA expr sortorder nulls */
+ -3, /* (135) sortlist ::= expr sortorder nulls */
+ -1, /* (136) sortorder ::= ASC */
+ -1, /* (137) sortorder ::= DESC */
+ 0, /* (138) sortorder ::= */
+ -2, /* (139) nulls ::= NULLS FIRST */
+ -2, /* (140) nulls ::= NULLS LAST */
+ 0, /* (141) nulls ::= */
+ 0, /* (142) groupby_opt ::= */
+ -3, /* (143) groupby_opt ::= GROUP BY nexprlist */
+ 0, /* (144) having_opt ::= */
+ -2, /* (145) having_opt ::= HAVING expr */
+ 0, /* (146) limit_opt ::= */
+ -2, /* (147) limit_opt ::= LIMIT expr */
+ -4, /* (148) limit_opt ::= LIMIT expr OFFSET expr */
+ -4, /* (149) limit_opt ::= LIMIT expr COMMA expr */
+ -8, /* (150) cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret orderby_opt limit_opt */
+ 0, /* (151) where_opt ::= */
+ -2, /* (152) where_opt ::= WHERE expr */
+ 0, /* (153) where_opt_ret ::= */
+ -2, /* (154) where_opt_ret ::= WHERE expr */
+ -2, /* (155) where_opt_ret ::= RETURNING selcollist */
+ -4, /* (156) where_opt_ret ::= WHERE expr RETURNING selcollist */
+ -11, /* (157) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret orderby_opt limit_opt */
+ -5, /* (158) setlist ::= setlist COMMA nm EQ expr */
+ -7, /* (159) setlist ::= setlist COMMA LP idlist RP EQ expr */
+ -3, /* (160) setlist ::= nm EQ expr */
+ -5, /* (161) setlist ::= LP idlist RP EQ expr */
+ -7, /* (162) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */
+ -8, /* (163) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning */
+ 0, /* (164) upsert ::= */
+ -2, /* (165) upsert ::= RETURNING selcollist */
+ -12, /* (166) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert */
+ -9, /* (167) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert */
+ -5, /* (168) upsert ::= ON CONFLICT DO NOTHING returning */
+ -8, /* (169) upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning */
+ -2, /* (170) returning ::= RETURNING selcollist */
+ -2, /* (171) insert_cmd ::= INSERT orconf */
+ -1, /* (172) insert_cmd ::= REPLACE */
+ 0, /* (173) idlist_opt ::= */
+ -3, /* (174) idlist_opt ::= LP idlist RP */
+ -3, /* (175) idlist ::= idlist COMMA nm */
+ -1, /* (176) idlist ::= nm */
+ -3, /* (177) expr ::= LP expr RP */
+ -1, /* (178) expr ::= ID|INDEXED */
+ -1, /* (179) expr ::= JOIN_KW */
+ -3, /* (180) expr ::= nm DOT nm */
+ -5, /* (181) expr ::= nm DOT nm DOT nm */
+ -1, /* (182) term ::= NULL|FLOAT|BLOB */
+ -1, /* (183) term ::= STRING */
+ -1, /* (184) term ::= INTEGER */
+ -1, /* (185) expr ::= VARIABLE */
+ -3, /* (186) expr ::= expr COLLATE ID|STRING */
+ -6, /* (187) expr ::= CAST LP expr AS typetoken RP */
+ -5, /* (188) expr ::= ID|INDEXED LP distinct exprlist RP */
+ -4, /* (189) expr ::= ID|INDEXED LP STAR RP */
+ -6, /* (190) expr ::= ID|INDEXED LP distinct exprlist RP filter_over */
+ -5, /* (191) expr ::= ID|INDEXED LP STAR RP filter_over */
+ -1, /* (192) term ::= CTIME_KW */
+ -5, /* (193) expr ::= LP nexprlist COMMA expr RP */
+ -3, /* (194) expr ::= expr AND expr */
+ -3, /* (195) expr ::= expr OR expr */
+ -3, /* (196) expr ::= expr LT|GT|GE|LE expr */
+ -3, /* (197) expr ::= expr EQ|NE expr */
+ -3, /* (198) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */
+ -3, /* (199) expr ::= expr PLUS|MINUS expr */
+ -3, /* (200) expr ::= expr STAR|SLASH|REM expr */
+ -3, /* (201) expr ::= expr CONCAT expr */
+ -2, /* (202) likeop ::= NOT LIKE_KW|MATCH */
+ -3, /* (203) expr ::= expr likeop expr */
+ -5, /* (204) expr ::= expr likeop expr ESCAPE expr */
+ -2, /* (205) expr ::= expr ISNULL|NOTNULL */
+ -3, /* (206) expr ::= expr NOT NULL */
+ -3, /* (207) expr ::= expr IS expr */
+ -4, /* (208) expr ::= expr IS NOT expr */
+ -6, /* (209) expr ::= expr IS NOT DISTINCT FROM expr */
+ -5, /* (210) expr ::= expr IS DISTINCT FROM expr */
+ -2, /* (211) expr ::= NOT expr */
+ -2, /* (212) expr ::= BITNOT expr */
+ -2, /* (213) expr ::= PLUS|MINUS expr */
+ -3, /* (214) expr ::= expr PTR expr */
+ -1, /* (215) between_op ::= BETWEEN */
+ -2, /* (216) between_op ::= NOT BETWEEN */
+ -5, /* (217) expr ::= expr between_op expr AND expr */
+ -1, /* (218) in_op ::= IN */
+ -2, /* (219) in_op ::= NOT IN */
+ -5, /* (220) expr ::= expr in_op LP exprlist RP */
+ -3, /* (221) expr ::= LP select RP */
+ -5, /* (222) expr ::= expr in_op LP select RP */
+ -5, /* (223) expr ::= expr in_op nm dbnm paren_exprlist */
+ -4, /* (224) expr ::= EXISTS LP select RP */
+ -5, /* (225) expr ::= CASE case_operand case_exprlist case_else END */
+ -5, /* (226) case_exprlist ::= case_exprlist WHEN expr THEN expr */
+ -4, /* (227) case_exprlist ::= WHEN expr THEN expr */
+ -2, /* (228) case_else ::= ELSE expr */
+ 0, /* (229) case_else ::= */
+ -1, /* (230) case_operand ::= expr */
+ 0, /* (231) case_operand ::= */
+ 0, /* (232) exprlist ::= */
+ -3, /* (233) nexprlist ::= nexprlist COMMA expr */
+ -1, /* (234) nexprlist ::= expr */
+ 0, /* (235) paren_exprlist ::= */
+ -3, /* (236) paren_exprlist ::= LP exprlist RP */
+ -12, /* (237) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
+ -1, /* (238) uniqueflag ::= UNIQUE */
+ 0, /* (239) uniqueflag ::= */
+ 0, /* (240) eidlist_opt ::= */
+ -3, /* (241) eidlist_opt ::= LP eidlist RP */
+ -5, /* (242) eidlist ::= eidlist COMMA nm collate sortorder */
+ -3, /* (243) eidlist ::= nm collate sortorder */
+ 0, /* (244) collate ::= */
+ -2, /* (245) collate ::= COLLATE ID|STRING */
+ -4, /* (246) cmd ::= DROP INDEX ifexists fullname */
+ -2, /* (247) cmd ::= VACUUM vinto */
+ -3, /* (248) cmd ::= VACUUM nm vinto */
+ -2, /* (249) vinto ::= INTO expr */
+ 0, /* (250) vinto ::= */
+ -3, /* (251) cmd ::= PRAGMA nm dbnm */
+ -5, /* (252) cmd ::= PRAGMA nm dbnm EQ nmnum */
+ -6, /* (253) cmd ::= PRAGMA nm dbnm LP nmnum RP */
+ -5, /* (254) cmd ::= PRAGMA nm dbnm EQ minus_num */
+ -6, /* (255) cmd ::= PRAGMA nm dbnm LP minus_num RP */
+ -2, /* (256) plus_num ::= PLUS INTEGER|FLOAT */
+ -2, /* (257) minus_num ::= MINUS INTEGER|FLOAT */
+ -5, /* (258) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
+ -11, /* (259) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
+ -1, /* (260) trigger_time ::= BEFORE|AFTER */
+ -2, /* (261) trigger_time ::= INSTEAD OF */
+ 0, /* (262) trigger_time ::= */
+ -1, /* (263) trigger_event ::= DELETE|INSERT */
+ -1, /* (264) trigger_event ::= UPDATE */
+ -3, /* (265) trigger_event ::= UPDATE OF idlist */
+ 0, /* (266) when_clause ::= */
+ -2, /* (267) when_clause ::= WHEN expr */
+ -3, /* (268) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
+ -2, /* (269) trigger_cmd_list ::= trigger_cmd SEMI */
+ -3, /* (270) trnm ::= nm DOT nm */
+ -3, /* (271) tridxby ::= INDEXED BY nm */
+ -2, /* (272) tridxby ::= NOT INDEXED */
+ -9, /* (273) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */
+ -8, /* (274) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
+ -6, /* (275) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
+ -3, /* (276) trigger_cmd ::= scanpt select scanpt */
+ -4, /* (277) expr ::= RAISE LP IGNORE RP */
+ -6, /* (278) expr ::= RAISE LP raisetype COMMA nm RP */
+ -1, /* (279) raisetype ::= ROLLBACK */
+ -1, /* (280) raisetype ::= ABORT */
+ -1, /* (281) raisetype ::= FAIL */
+ -4, /* (282) cmd ::= DROP TRIGGER ifexists fullname */
+ -6, /* (283) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
+ -3, /* (284) cmd ::= DETACH database_kw_opt expr */
+ 0, /* (285) key_opt ::= */
+ -2, /* (286) key_opt ::= KEY expr */
+ -1, /* (287) cmd ::= REINDEX */
+ -3, /* (288) cmd ::= REINDEX nm dbnm */
+ -1, /* (289) cmd ::= ANALYZE */
+ -3, /* (290) cmd ::= ANALYZE nm dbnm */
+ -6, /* (291) cmd ::= ALTER TABLE fullname RENAME TO nm */
+ -7, /* (292) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
+ -6, /* (293) cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */
+ -1, /* (294) add_column_fullname ::= fullname */
+ -8, /* (295) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
+ -1, /* (296) cmd ::= create_vtab */
+ -4, /* (297) cmd ::= create_vtab LP vtabarglist RP */
+ -8, /* (298) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
+ 0, /* (299) vtabarg ::= */
+ -1, /* (300) vtabargtoken ::= ANY */
+ -3, /* (301) vtabargtoken ::= lp anylist RP */
+ -1, /* (302) lp ::= LP */
+ -2, /* (303) with ::= WITH wqlist */
+ -3, /* (304) with ::= WITH RECURSIVE wqlist */
+ -1, /* (305) wqas ::= AS */
+ -2, /* (306) wqas ::= AS MATERIALIZED */
+ -3, /* (307) wqas ::= AS NOT MATERIALIZED */
+ -6, /* (308) wqitem ::= nm eidlist_opt wqas LP select RP */
+ -1, /* (309) wqlist ::= wqitem */
+ -3, /* (310) wqlist ::= wqlist COMMA wqitem */
+ -1, /* (311) windowdefn_list ::= windowdefn */
+ -3, /* (312) windowdefn_list ::= windowdefn_list COMMA windowdefn */
+ -5, /* (313) windowdefn ::= nm AS LP window RP */
+ -5, /* (314) window ::= PARTITION BY nexprlist orderby_opt frame_opt */
+ -6, /* (315) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */
+ -4, /* (316) window ::= ORDER BY sortlist frame_opt */
+ -5, /* (317) window ::= nm ORDER BY sortlist frame_opt */
+ -1, /* (318) window ::= frame_opt */
+ -2, /* (319) window ::= nm frame_opt */
+ 0, /* (320) frame_opt ::= */
+ -3, /* (321) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */
+ -6, /* (322) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */
+ -1, /* (323) range_or_rows ::= RANGE|ROWS|GROUPS */
+ -1, /* (324) frame_bound_s ::= frame_bound */
+ -2, /* (325) frame_bound_s ::= UNBOUNDED PRECEDING */
+ -1, /* (326) frame_bound_e ::= frame_bound */
+ -2, /* (327) frame_bound_e ::= UNBOUNDED FOLLOWING */
+ -2, /* (328) frame_bound ::= expr PRECEDING|FOLLOWING */
+ -2, /* (329) frame_bound ::= CURRENT ROW */
+ 0, /* (330) frame_exclude_opt ::= */
+ -2, /* (331) frame_exclude_opt ::= EXCLUDE frame_exclude */
+ -2, /* (332) frame_exclude ::= NO OTHERS */
+ -2, /* (333) frame_exclude ::= CURRENT ROW */
+ -1, /* (334) frame_exclude ::= GROUP|TIES */
+ -2, /* (335) window_clause ::= WINDOW windowdefn_list */
+ -2, /* (336) filter_over ::= filter_clause over_clause */
+ -1, /* (337) filter_over ::= over_clause */
+ -1, /* (338) filter_over ::= filter_clause */
+ -4, /* (339) over_clause ::= OVER LP window RP */
+ -2, /* (340) over_clause ::= OVER nm */
+ -5, /* (341) filter_clause ::= FILTER LP WHERE expr RP */
+ -1, /* (342) input ::= cmdlist */
+ -2, /* (343) cmdlist ::= cmdlist ecmd */
+ -1, /* (344) cmdlist ::= ecmd */
+ -1, /* (345) ecmd ::= SEMI */
+ -2, /* (346) ecmd ::= cmdx SEMI */
+ -3, /* (347) ecmd ::= explain cmdx SEMI */
+ 0, /* (348) trans_opt ::= */
+ -1, /* (349) trans_opt ::= TRANSACTION */
+ -2, /* (350) trans_opt ::= TRANSACTION nm */
+ -1, /* (351) savepoint_opt ::= SAVEPOINT */
+ 0, /* (352) savepoint_opt ::= */
+ -2, /* (353) cmd ::= create_table create_table_args */
+ -1, /* (354) table_option_set ::= table_option */
+ -4, /* (355) columnlist ::= columnlist COMMA columnname carglist */
+ -2, /* (356) columnlist ::= columnname carglist */
+ -1, /* (357) nm ::= ID|INDEXED */
+ -1, /* (358) nm ::= STRING */
+ -1, /* (359) nm ::= JOIN_KW */
+ -1, /* (360) typetoken ::= typename */
+ -1, /* (361) typename ::= ID|STRING */
+ -1, /* (362) signed ::= plus_num */
+ -1, /* (363) signed ::= minus_num */
+ -2, /* (364) carglist ::= carglist ccons */
+ 0, /* (365) carglist ::= */
+ -2, /* (366) ccons ::= NULL onconf */
+ -4, /* (367) ccons ::= GENERATED ALWAYS AS generated */
+ -2, /* (368) ccons ::= AS generated */
+ -2, /* (369) conslist_opt ::= COMMA conslist */
+ -3, /* (370) conslist ::= conslist tconscomma tcons */
+ -1, /* (371) conslist ::= tcons */
+ 0, /* (372) tconscomma ::= */
+ -1, /* (373) defer_subclause_opt ::= defer_subclause */
+ -1, /* (374) resolvetype ::= raisetype */
+ -1, /* (375) selectnowith ::= oneselect */
+ -1, /* (376) oneselect ::= values */
+ -2, /* (377) sclp ::= selcollist COMMA */
+ -1, /* (378) as ::= ID|STRING */
+ -1, /* (379) indexed_opt ::= indexed_by */
+ 0, /* (380) returning ::= */
+ -1, /* (381) expr ::= term */
+ -1, /* (382) likeop ::= LIKE_KW|MATCH */
+ -1, /* (383) exprlist ::= nexprlist */
+ -1, /* (384) nmnum ::= plus_num */
+ -1, /* (385) nmnum ::= nm */
+ -1, /* (386) nmnum ::= ON */
+ -1, /* (387) nmnum ::= DELETE */
+ -1, /* (388) nmnum ::= DEFAULT */
+ -1, /* (389) plus_num ::= INTEGER|FLOAT */
+ 0, /* (390) foreach_clause ::= */
+ -3, /* (391) foreach_clause ::= FOR EACH ROW */
+ -1, /* (392) trnm ::= nm */
+ 0, /* (393) tridxby ::= */
+ -1, /* (394) database_kw_opt ::= DATABASE */
+ 0, /* (395) database_kw_opt ::= */
+ 0, /* (396) kwcolumn_opt ::= */
+ -1, /* (397) kwcolumn_opt ::= COLUMNKW */
+ -1, /* (398) vtabarglist ::= vtabarg */
+ -3, /* (399) vtabarglist ::= vtabarglist COMMA vtabarg */
+ -2, /* (400) vtabarg ::= vtabarg vtabargtoken */
+ 0, /* (401) anylist ::= */
+ -4, /* (402) anylist ::= anylist LP anylist RP */
+ -2, /* (403) anylist ::= anylist ANY */
+ 0, /* (404) with ::= */
};
static void yy_accept(yyParser*); /* Forward Declaration */
@@ -163166,55 +172457,6 @@ static YYACTIONTYPE yy_reduce(
(void)yyLookahead;
(void)yyLookaheadToken;
yymsp = yypParser->yytos;
- assert( yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) );
-#ifndef NDEBUG
- if( yyTraceFILE ){
- yysize = yyRuleInfoNRhs[yyruleno];
- if( yysize ){
- fprintf(yyTraceFILE, "%sReduce %d [%s]%s, pop back to state %d.\n",
- yyTracePrompt,
- yyruleno, yyRuleName[yyruleno],
- yyruleno<YYNRULE_WITH_ACTION ? "" : " without external action",
- yymsp[yysize].stateno);
- }else{
- fprintf(yyTraceFILE, "%sReduce %d [%s]%s.\n",
- yyTracePrompt, yyruleno, yyRuleName[yyruleno],
- yyruleno<YYNRULE_WITH_ACTION ? "" : " without external action");
- }
- }
-#endif /* NDEBUG */
-
- /* Check that the stack is large enough to grow by a single entry
- ** if the RHS of the rule is empty. This ensures that there is room
- ** enough on the stack to push the LHS value */
- if( yyRuleInfoNRhs[yyruleno]==0 ){
-#ifdef YYTRACKMAXSTACKDEPTH
- if( (int)(yypParser->yytos - yypParser->yystack)>yypParser->yyhwm ){
- yypParser->yyhwm++;
- assert( yypParser->yyhwm == (int)(yypParser->yytos - yypParser->yystack));
- }
-#endif
-#if YYSTACKDEPTH>0
- if( yypParser->yytos>=yypParser->yystackEnd ){
- yyStackOverflow(yypParser);
- /* The call to yyStackOverflow() above pops the stack until it is
- ** empty, causing the main parser loop to exit. So the return value
- ** is never used and does not matter. */
- return 0;
- }
-#else
- if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz-1] ){
- if( yyGrowStack(yypParser) ){
- yyStackOverflow(yypParser);
- /* The call to yyStackOverflow() above pops the stack until it is
- ** empty, causing the main parser loop to exit. So the return value
- ** is never used and does not matter. */
- return 0;
- }
- yymsp = yypParser->yytos;
- }
-#endif
- }
switch( yyruleno ){
/* Beginning here are the reduction cases. A typical example
@@ -163237,16 +172479,16 @@ static YYACTIONTYPE yy_reduce(
{ sqlcipher_sqlite3FinishCoding(pParse); }
break;
case 3: /* cmd ::= BEGIN transtype trans_opt */
-{sqlcipher_sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy192);}
+{sqlcipher_sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy394);}
break;
case 4: /* transtype ::= */
-{yymsp[1].minor.yy192 = TK_DEFERRED;}
+{yymsp[1].minor.yy394 = TK_DEFERRED;}
break;
case 5: /* transtype ::= DEFERRED */
case 6: /* transtype ::= IMMEDIATE */ yytestcase(yyruleno==6);
case 7: /* transtype ::= EXCLUSIVE */ yytestcase(yyruleno==7);
- case 306: /* range_or_rows ::= RANGE|ROWS|GROUPS */ yytestcase(yyruleno==306);
-{yymsp[0].minor.yy192 = yymsp[0].major; /*A-overwrites-X*/}
+ case 323: /* range_or_rows ::= RANGE|ROWS|GROUPS */ yytestcase(yyruleno==323);
+{yymsp[0].minor.yy394 = yymsp[0].major; /*A-overwrites-X*/}
break;
case 8: /* cmd ::= COMMIT|END trans_opt */
case 9: /* cmd ::= ROLLBACK trans_opt */ yytestcase(yyruleno==9);
@@ -163269,7 +172511,7 @@ static YYACTIONTYPE yy_reduce(
break;
case 13: /* create_table ::= createkw temp TABLE ifnotexists nm dbnm */
{
- sqlcipher_sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy192,0,0,yymsp[-2].minor.yy192);
+ sqlcipher_sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy394,0,0,yymsp[-2].minor.yy394);
}
break;
case 14: /* createkw ::= CREATE */
@@ -163277,96 +172519,112 @@ static YYACTIONTYPE yy_reduce(
break;
case 15: /* ifnotexists ::= */
case 18: /* temp ::= */ yytestcase(yyruleno==18);
- case 21: /* table_options ::= */ yytestcase(yyruleno==21);
- case 45: /* autoinc ::= */ yytestcase(yyruleno==45);
- case 60: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==60);
- case 70: /* defer_subclause_opt ::= */ yytestcase(yyruleno==70);
- case 79: /* ifexists ::= */ yytestcase(yyruleno==79);
- case 96: /* distinct ::= */ yytestcase(yyruleno==96);
- case 232: /* collate ::= */ yytestcase(yyruleno==232);
-{yymsp[1].minor.yy192 = 0;}
+ case 47: /* autoinc ::= */ yytestcase(yyruleno==47);
+ case 62: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==62);
+ case 72: /* defer_subclause_opt ::= */ yytestcase(yyruleno==72);
+ case 81: /* ifexists ::= */ yytestcase(yyruleno==81);
+ case 98: /* distinct ::= */ yytestcase(yyruleno==98);
+ case 244: /* collate ::= */ yytestcase(yyruleno==244);
+{yymsp[1].minor.yy394 = 0;}
break;
case 16: /* ifnotexists ::= IF NOT EXISTS */
-{yymsp[-2].minor.yy192 = 1;}
+{yymsp[-2].minor.yy394 = 1;}
break;
case 17: /* temp ::= TEMP */
- case 46: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==46);
-{yymsp[0].minor.yy192 = 1;}
+{yymsp[0].minor.yy394 = pParse->db->init.busy==0;}
break;
- case 19: /* create_table_args ::= LP columnlist conslist_opt RP table_options */
+ case 19: /* create_table_args ::= LP columnlist conslist_opt RP table_option_set */
{
- sqlcipher_sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy192,0);
+ sqlcipher_sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy285,0);
}
break;
case 20: /* create_table_args ::= AS select */
{
- sqlcipher_sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy539);
- sqlcipher_sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy539);
+ sqlcipher_sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy47);
+ sqlcipher_sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy47);
}
break;
- case 22: /* table_options ::= WITHOUT nm */
+ case 21: /* table_option_set ::= */
+{yymsp[1].minor.yy285 = 0;}
+ break;
+ case 22: /* table_option_set ::= table_option_set COMMA table_option */
+{yylhsminor.yy285 = yymsp[-2].minor.yy285|yymsp[0].minor.yy285;}
+ yymsp[-2].minor.yy285 = yylhsminor.yy285;
+ break;
+ case 23: /* table_option ::= WITHOUT nm */
{
if( yymsp[0].minor.yy0.n==5 && sqlcipher_sqlite3_strnicmp(yymsp[0].minor.yy0.z,"rowid",5)==0 ){
- yymsp[-1].minor.yy192 = TF_WithoutRowid | TF_NoVisibleRowid;
+ yymsp[-1].minor.yy285 = TF_WithoutRowid | TF_NoVisibleRowid;
+ }else{
+ yymsp[-1].minor.yy285 = 0;
+ sqlcipher_sqlite3ErrorMsg(pParse, "unknown table option: %.*s", yymsp[0].minor.yy0.n, yymsp[0].minor.yy0.z);
+ }
+}
+ break;
+ case 24: /* table_option ::= nm */
+{
+ if( yymsp[0].minor.yy0.n==6 && sqlcipher_sqlite3_strnicmp(yymsp[0].minor.yy0.z,"strict",6)==0 ){
+ yylhsminor.yy285 = TF_Strict;
}else{
- yymsp[-1].minor.yy192 = 0;
+ yylhsminor.yy285 = 0;
sqlcipher_sqlite3ErrorMsg(pParse, "unknown table option: %.*s", yymsp[0].minor.yy0.n, yymsp[0].minor.yy0.z);
}
}
+ yymsp[0].minor.yy285 = yylhsminor.yy285;
break;
- case 23: /* columnname ::= nm typetoken */
-{sqlcipher_sqlite3AddColumn(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);}
+ case 25: /* columnname ::= nm typetoken */
+{sqlcipher_sqlite3AddColumn(pParse,yymsp[-1].minor.yy0,yymsp[0].minor.yy0);}
break;
- case 24: /* typetoken ::= */
- case 63: /* conslist_opt ::= */ yytestcase(yyruleno==63);
- case 102: /* as ::= */ yytestcase(yyruleno==102);
+ case 26: /* typetoken ::= */
+ case 65: /* conslist_opt ::= */ yytestcase(yyruleno==65);
+ case 104: /* as ::= */ yytestcase(yyruleno==104);
{yymsp[1].minor.yy0.n = 0; yymsp[1].minor.yy0.z = 0;}
break;
- case 25: /* typetoken ::= typename LP signed RP */
+ case 27: /* typetoken ::= typename LP signed RP */
{
yymsp[-3].minor.yy0.n = (int)(&yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-3].minor.yy0.z);
}
break;
- case 26: /* typetoken ::= typename LP signed COMMA signed RP */
+ case 28: /* typetoken ::= typename LP signed COMMA signed RP */
{
yymsp[-5].minor.yy0.n = (int)(&yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-5].minor.yy0.z);
}
break;
- case 27: /* typename ::= typename ID|STRING */
+ case 29: /* typename ::= typename ID|STRING */
{yymsp[-1].minor.yy0.n=yymsp[0].minor.yy0.n+(int)(yymsp[0].minor.yy0.z-yymsp[-1].minor.yy0.z);}
break;
- case 28: /* scanpt ::= */
+ case 30: /* scanpt ::= */
{
assert( yyLookahead!=YYNOCODE );
- yymsp[1].minor.yy436 = yyLookaheadToken.z;
+ yymsp[1].minor.yy522 = yyLookaheadToken.z;
}
break;
- case 29: /* scantok ::= */
+ case 31: /* scantok ::= */
{
assert( yyLookahead!=YYNOCODE );
yymsp[1].minor.yy0 = yyLookaheadToken;
}
break;
- case 30: /* ccons ::= CONSTRAINT nm */
- case 65: /* tcons ::= CONSTRAINT nm */ yytestcase(yyruleno==65);
+ case 32: /* ccons ::= CONSTRAINT nm */
+ case 67: /* tcons ::= CONSTRAINT nm */ yytestcase(yyruleno==67);
{pParse->constraintName = yymsp[0].minor.yy0;}
break;
- case 31: /* ccons ::= DEFAULT scantok term */
-{sqlcipher_sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy202,yymsp[-1].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);}
+ case 33: /* ccons ::= DEFAULT scantok term */
+{sqlcipher_sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy528,yymsp[-1].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);}
break;
- case 32: /* ccons ::= DEFAULT LP expr RP */
-{sqlcipher_sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy202,yymsp[-2].minor.yy0.z+1,yymsp[0].minor.yy0.z);}
+ case 34: /* ccons ::= DEFAULT LP expr RP */
+{sqlcipher_sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy528,yymsp[-2].minor.yy0.z+1,yymsp[0].minor.yy0.z);}
break;
- case 33: /* ccons ::= DEFAULT PLUS scantok term */
-{sqlcipher_sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy202,yymsp[-2].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);}
+ case 35: /* ccons ::= DEFAULT PLUS scantok term */
+{sqlcipher_sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy528,yymsp[-2].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);}
break;
- case 34: /* ccons ::= DEFAULT MINUS scantok term */
+ case 36: /* ccons ::= DEFAULT MINUS scantok term */
{
- Expr *p = sqlcipher_sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy202, 0);
+ Expr *p = sqlcipher_sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy528, 0);
sqlcipher_sqlite3AddDefaultValue(pParse,p,yymsp[-2].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);
}
break;
- case 35: /* ccons ::= DEFAULT scantok ID|INDEXED */
+ case 37: /* ccons ::= DEFAULT scantok ID|INDEXED */
{
Expr *p = tokenExpr(pParse, TK_STRING, yymsp[0].minor.yy0);
if( p ){
@@ -163376,323 +172634,316 @@ static YYACTIONTYPE yy_reduce(
sqlcipher_sqlite3AddDefaultValue(pParse,p,yymsp[0].minor.yy0.z,yymsp[0].minor.yy0.z+yymsp[0].minor.yy0.n);
}
break;
- case 36: /* ccons ::= NOT NULL onconf */
-{sqlcipher_sqlite3AddNotNull(pParse, yymsp[0].minor.yy192);}
+ case 38: /* ccons ::= NOT NULL onconf */
+{sqlcipher_sqlite3AddNotNull(pParse, yymsp[0].minor.yy394);}
break;
- case 37: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */
-{sqlcipher_sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy192,yymsp[0].minor.yy192,yymsp[-2].minor.yy192);}
+ case 39: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */
+{sqlcipher_sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy394,yymsp[0].minor.yy394,yymsp[-2].minor.yy394);}
break;
- case 38: /* ccons ::= UNIQUE onconf */
-{sqlcipher_sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy192,0,0,0,0,
+ case 40: /* ccons ::= UNIQUE onconf */
+{sqlcipher_sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy394,0,0,0,0,
SQLITE_IDXTYPE_UNIQUE);}
break;
- case 39: /* ccons ::= CHECK LP expr RP */
-{sqlcipher_sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy202,yymsp[-2].minor.yy0.z,yymsp[0].minor.yy0.z);}
+ case 41: /* ccons ::= CHECK LP expr RP */
+{sqlcipher_sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy528,yymsp[-2].minor.yy0.z,yymsp[0].minor.yy0.z);}
break;
- case 40: /* ccons ::= REFERENCES nm eidlist_opt refargs */
-{sqlcipher_sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy242,yymsp[0].minor.yy192);}
+ case 42: /* ccons ::= REFERENCES nm eidlist_opt refargs */
+{sqlcipher_sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy322,yymsp[0].minor.yy394);}
break;
- case 41: /* ccons ::= defer_subclause */
-{sqlcipher_sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy192);}
+ case 43: /* ccons ::= defer_subclause */
+{sqlcipher_sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy394);}
break;
- case 42: /* ccons ::= COLLATE ID|STRING */
+ case 44: /* ccons ::= COLLATE ID|STRING */
{sqlcipher_sqlite3AddCollateType(pParse, &yymsp[0].minor.yy0);}
break;
- case 43: /* generated ::= LP expr RP */
-{sqlcipher_sqlite3AddGenerated(pParse,yymsp[-1].minor.yy202,0);}
+ case 45: /* generated ::= LP expr RP */
+{sqlcipher_sqlite3AddGenerated(pParse,yymsp[-1].minor.yy528,0);}
+ break;
+ case 46: /* generated ::= LP expr RP ID */
+{sqlcipher_sqlite3AddGenerated(pParse,yymsp[-2].minor.yy528,&yymsp[0].minor.yy0);}
break;
- case 44: /* generated ::= LP expr RP ID */
-{sqlcipher_sqlite3AddGenerated(pParse,yymsp[-2].minor.yy202,&yymsp[0].minor.yy0);}
+ case 48: /* autoinc ::= AUTOINCR */
+{yymsp[0].minor.yy394 = 1;}
break;
- case 47: /* refargs ::= */
-{ yymsp[1].minor.yy192 = OE_None*0x0101; /* EV: R-19803-45884 */}
+ case 49: /* refargs ::= */
+{ yymsp[1].minor.yy394 = OE_None*0x0101; /* EV: R-19803-45884 */}
break;
- case 48: /* refargs ::= refargs refarg */
-{ yymsp[-1].minor.yy192 = (yymsp[-1].minor.yy192 & ~yymsp[0].minor.yy207.mask) | yymsp[0].minor.yy207.value; }
+ case 50: /* refargs ::= refargs refarg */
+{ yymsp[-1].minor.yy394 = (yymsp[-1].minor.yy394 & ~yymsp[0].minor.yy231.mask) | yymsp[0].minor.yy231.value; }
break;
- case 49: /* refarg ::= MATCH nm */
-{ yymsp[-1].minor.yy207.value = 0; yymsp[-1].minor.yy207.mask = 0x000000; }
+ case 51: /* refarg ::= MATCH nm */
+{ yymsp[-1].minor.yy231.value = 0; yymsp[-1].minor.yy231.mask = 0x000000; }
break;
- case 50: /* refarg ::= ON INSERT refact */
-{ yymsp[-2].minor.yy207.value = 0; yymsp[-2].minor.yy207.mask = 0x000000; }
+ case 52: /* refarg ::= ON INSERT refact */
+{ yymsp[-2].minor.yy231.value = 0; yymsp[-2].minor.yy231.mask = 0x000000; }
break;
- case 51: /* refarg ::= ON DELETE refact */
-{ yymsp[-2].minor.yy207.value = yymsp[0].minor.yy192; yymsp[-2].minor.yy207.mask = 0x0000ff; }
+ case 53: /* refarg ::= ON DELETE refact */
+{ yymsp[-2].minor.yy231.value = yymsp[0].minor.yy394; yymsp[-2].minor.yy231.mask = 0x0000ff; }
break;
- case 52: /* refarg ::= ON UPDATE refact */
-{ yymsp[-2].minor.yy207.value = yymsp[0].minor.yy192<<8; yymsp[-2].minor.yy207.mask = 0x00ff00; }
+ case 54: /* refarg ::= ON UPDATE refact */
+{ yymsp[-2].minor.yy231.value = yymsp[0].minor.yy394<<8; yymsp[-2].minor.yy231.mask = 0x00ff00; }
break;
- case 53: /* refact ::= SET NULL */
-{ yymsp[-1].minor.yy192 = OE_SetNull; /* EV: R-33326-45252 */}
+ case 55: /* refact ::= SET NULL */
+{ yymsp[-1].minor.yy394 = OE_SetNull; /* EV: R-33326-45252 */}
break;
- case 54: /* refact ::= SET DEFAULT */
-{ yymsp[-1].minor.yy192 = OE_SetDflt; /* EV: R-33326-45252 */}
+ case 56: /* refact ::= SET DEFAULT */
+{ yymsp[-1].minor.yy394 = OE_SetDflt; /* EV: R-33326-45252 */}
break;
- case 55: /* refact ::= CASCADE */
-{ yymsp[0].minor.yy192 = OE_Cascade; /* EV: R-33326-45252 */}
+ case 57: /* refact ::= CASCADE */
+{ yymsp[0].minor.yy394 = OE_Cascade; /* EV: R-33326-45252 */}
break;
- case 56: /* refact ::= RESTRICT */
-{ yymsp[0].minor.yy192 = OE_Restrict; /* EV: R-33326-45252 */}
+ case 58: /* refact ::= RESTRICT */
+{ yymsp[0].minor.yy394 = OE_Restrict; /* EV: R-33326-45252 */}
break;
- case 57: /* refact ::= NO ACTION */
-{ yymsp[-1].minor.yy192 = OE_None; /* EV: R-33326-45252 */}
+ case 59: /* refact ::= NO ACTION */
+{ yymsp[-1].minor.yy394 = OE_None; /* EV: R-33326-45252 */}
break;
- case 58: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
-{yymsp[-2].minor.yy192 = 0;}
+ case 60: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
+{yymsp[-2].minor.yy394 = 0;}
break;
- case 59: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
- case 74: /* orconf ::= OR resolvetype */ yytestcase(yyruleno==74);
- case 162: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==162);
-{yymsp[-1].minor.yy192 = yymsp[0].minor.yy192;}
+ case 61: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
+ case 76: /* orconf ::= OR resolvetype */ yytestcase(yyruleno==76);
+ case 171: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==171);
+{yymsp[-1].minor.yy394 = yymsp[0].minor.yy394;}
break;
- case 61: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */
- case 78: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==78);
- case 204: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==204);
- case 207: /* in_op ::= NOT IN */ yytestcase(yyruleno==207);
- case 233: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==233);
-{yymsp[-1].minor.yy192 = 1;}
+ case 63: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */
+ case 80: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==80);
+ case 216: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==216);
+ case 219: /* in_op ::= NOT IN */ yytestcase(yyruleno==219);
+ case 245: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==245);
+{yymsp[-1].minor.yy394 = 1;}
break;
- case 62: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */
-{yymsp[-1].minor.yy192 = 0;}
+ case 64: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */
+{yymsp[-1].minor.yy394 = 0;}
break;
- case 64: /* tconscomma ::= COMMA */
+ case 66: /* tconscomma ::= COMMA */
{pParse->constraintName.n = 0;}
break;
- case 66: /* tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */
-{sqlcipher_sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy242,yymsp[0].minor.yy192,yymsp[-2].minor.yy192,0);}
+ case 68: /* tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */
+{sqlcipher_sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy322,yymsp[0].minor.yy394,yymsp[-2].minor.yy394,0);}
break;
- case 67: /* tcons ::= UNIQUE LP sortlist RP onconf */
-{sqlcipher_sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy242,yymsp[0].minor.yy192,0,0,0,0,
+ case 69: /* tcons ::= UNIQUE LP sortlist RP onconf */
+{sqlcipher_sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy322,yymsp[0].minor.yy394,0,0,0,0,
SQLITE_IDXTYPE_UNIQUE);}
break;
- case 68: /* tcons ::= CHECK LP expr RP onconf */
-{sqlcipher_sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy202,yymsp[-3].minor.yy0.z,yymsp[-1].minor.yy0.z);}
+ case 70: /* tcons ::= CHECK LP expr RP onconf */
+{sqlcipher_sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy528,yymsp[-3].minor.yy0.z,yymsp[-1].minor.yy0.z);}
break;
- case 69: /* tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */
+ case 71: /* tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */
{
- sqlcipher_sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy242, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy242, yymsp[-1].minor.yy192);
- sqlcipher_sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy192);
+ sqlcipher_sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy322, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy322, yymsp[-1].minor.yy394);
+ sqlcipher_sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy394);
}
break;
- case 71: /* onconf ::= */
- case 73: /* orconf ::= */ yytestcase(yyruleno==73);
-{yymsp[1].minor.yy192 = OE_Default;}
+ case 73: /* onconf ::= */
+ case 75: /* orconf ::= */ yytestcase(yyruleno==75);
+{yymsp[1].minor.yy394 = OE_Default;}
break;
- case 72: /* onconf ::= ON CONFLICT resolvetype */
-{yymsp[-2].minor.yy192 = yymsp[0].minor.yy192;}
+ case 74: /* onconf ::= ON CONFLICT resolvetype */
+{yymsp[-2].minor.yy394 = yymsp[0].minor.yy394;}
break;
- case 75: /* resolvetype ::= IGNORE */
-{yymsp[0].minor.yy192 = OE_Ignore;}
+ case 77: /* resolvetype ::= IGNORE */
+{yymsp[0].minor.yy394 = OE_Ignore;}
break;
- case 76: /* resolvetype ::= REPLACE */
- case 163: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==163);
-{yymsp[0].minor.yy192 = OE_Replace;}
+ case 78: /* resolvetype ::= REPLACE */
+ case 172: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==172);
+{yymsp[0].minor.yy394 = OE_Replace;}
break;
- case 77: /* cmd ::= DROP TABLE ifexists fullname */
+ case 79: /* cmd ::= DROP TABLE ifexists fullname */
{
- sqlcipher_sqlite3DropTable(pParse, yymsp[0].minor.yy47, 0, yymsp[-1].minor.yy192);
+ sqlcipher_sqlite3DropTable(pParse, yymsp[0].minor.yy131, 0, yymsp[-1].minor.yy394);
}
break;
- case 80: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */
+ case 82: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */
{
- sqlcipher_sqlite3CreateView(pParse, &yymsp[-8].minor.yy0, &yymsp[-4].minor.yy0, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy242, yymsp[0].minor.yy539, yymsp[-7].minor.yy192, yymsp[-5].minor.yy192);
+ sqlcipher_sqlite3CreateView(pParse, &yymsp[-8].minor.yy0, &yymsp[-4].minor.yy0, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy322, yymsp[0].minor.yy47, yymsp[-7].minor.yy394, yymsp[-5].minor.yy394);
}
break;
- case 81: /* cmd ::= DROP VIEW ifexists fullname */
+ case 83: /* cmd ::= DROP VIEW ifexists fullname */
{
- sqlcipher_sqlite3DropTable(pParse, yymsp[0].minor.yy47, 1, yymsp[-1].minor.yy192);
+ sqlcipher_sqlite3DropTable(pParse, yymsp[0].minor.yy131, 1, yymsp[-1].minor.yy394);
}
break;
- case 82: /* cmd ::= select */
+ case 84: /* cmd ::= select */
{
SelectDest dest = {SRT_Output, 0, 0, 0, 0, 0, 0};
- sqlcipher_sqlite3Select(pParse, yymsp[0].minor.yy539, &dest);
- sqlcipher_sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy539);
+ sqlcipher_sqlite3Select(pParse, yymsp[0].minor.yy47, &dest);
+ sqlcipher_sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy47);
}
break;
- case 83: /* select ::= WITH wqlist selectnowith */
-{
- Select *p = yymsp[0].minor.yy539;
- if( p ){
- p->pWith = yymsp[-1].minor.yy131;
- parserDoubleLinkSelect(pParse, p);
- }else{
- sqlcipher_sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy131);
- }
- yymsp[-2].minor.yy539 = p;
-}
+ case 85: /* select ::= WITH wqlist selectnowith */
+{yymsp[-2].minor.yy47 = attachWithToSelect(pParse,yymsp[0].minor.yy47,yymsp[-1].minor.yy521);}
break;
- case 84: /* select ::= WITH RECURSIVE wqlist selectnowith */
-{
- Select *p = yymsp[0].minor.yy539;
- if( p ){
- p->pWith = yymsp[-1].minor.yy131;
- parserDoubleLinkSelect(pParse, p);
- }else{
- sqlcipher_sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy131);
- }
- yymsp[-3].minor.yy539 = p;
-}
+ case 86: /* select ::= WITH RECURSIVE wqlist selectnowith */
+{yymsp[-3].minor.yy47 = attachWithToSelect(pParse,yymsp[0].minor.yy47,yymsp[-1].minor.yy521);}
break;
- case 85: /* select ::= selectnowith */
+ case 87: /* select ::= selectnowith */
{
- Select *p = yymsp[0].minor.yy539;
+ Select *p = yymsp[0].minor.yy47;
if( p ){
parserDoubleLinkSelect(pParse, p);
}
- yymsp[0].minor.yy539 = p; /*A-overwrites-X*/
+ yymsp[0].minor.yy47 = p; /*A-overwrites-X*/
}
break;
- case 86: /* selectnowith ::= selectnowith multiselect_op oneselect */
+ case 88: /* selectnowith ::= selectnowith multiselect_op oneselect */
{
- Select *pRhs = yymsp[0].minor.yy539;
- Select *pLhs = yymsp[-2].minor.yy539;
+ Select *pRhs = yymsp[0].minor.yy47;
+ Select *pLhs = yymsp[-2].minor.yy47;
if( pRhs && pRhs->pPrior ){
SrcList *pFrom;
Token x;
x.n = 0;
parserDoubleLinkSelect(pParse, pRhs);
- pFrom = sqlcipher_sqlite3SrcListAppendFromTerm(pParse,0,0,0,&x,pRhs,0,0);
+ pFrom = sqlcipher_sqlite3SrcListAppendFromTerm(pParse,0,0,0,&x,pRhs,0);
pRhs = sqlcipher_sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0);
}
if( pRhs ){
- pRhs->op = (u8)yymsp[-1].minor.yy192;
+ pRhs->op = (u8)yymsp[-1].minor.yy394;
pRhs->pPrior = pLhs;
if( ALWAYS(pLhs) ) pLhs->selFlags &= ~SF_MultiValue;
pRhs->selFlags &= ~SF_MultiValue;
- if( yymsp[-1].minor.yy192!=TK_ALL ) pParse->hasCompound = 1;
+ if( yymsp[-1].minor.yy394!=TK_ALL ) pParse->hasCompound = 1;
}else{
sqlcipher_sqlite3SelectDelete(pParse->db, pLhs);
}
- yymsp[-2].minor.yy539 = pRhs;
+ yymsp[-2].minor.yy47 = pRhs;
}
break;
- case 87: /* multiselect_op ::= UNION */
- case 89: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==89);
-{yymsp[0].minor.yy192 = yymsp[0].major; /*A-overwrites-OP*/}
+ case 89: /* multiselect_op ::= UNION */
+ case 91: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==91);
+{yymsp[0].minor.yy394 = yymsp[0].major; /*A-overwrites-OP*/}
break;
- case 88: /* multiselect_op ::= UNION ALL */
-{yymsp[-1].minor.yy192 = TK_ALL;}
+ case 90: /* multiselect_op ::= UNION ALL */
+{yymsp[-1].minor.yy394 = TK_ALL;}
break;
- case 90: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
+ case 92: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
{
- yymsp[-8].minor.yy539 = sqlcipher_sqlite3SelectNew(pParse,yymsp[-6].minor.yy242,yymsp[-5].minor.yy47,yymsp[-4].minor.yy202,yymsp[-3].minor.yy242,yymsp[-2].minor.yy202,yymsp[-1].minor.yy242,yymsp[-7].minor.yy192,yymsp[0].minor.yy202);
+ yymsp[-8].minor.yy47 = sqlcipher_sqlite3SelectNew(pParse,yymsp[-6].minor.yy322,yymsp[-5].minor.yy131,yymsp[-4].minor.yy528,yymsp[-3].minor.yy322,yymsp[-2].minor.yy528,yymsp[-1].minor.yy322,yymsp[-7].minor.yy394,yymsp[0].minor.yy528);
}
break;
- case 91: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */
+ case 93: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */
{
- yymsp[-9].minor.yy539 = sqlcipher_sqlite3SelectNew(pParse,yymsp[-7].minor.yy242,yymsp[-6].minor.yy47,yymsp[-5].minor.yy202,yymsp[-4].minor.yy242,yymsp[-3].minor.yy202,yymsp[-1].minor.yy242,yymsp[-8].minor.yy192,yymsp[0].minor.yy202);
- if( yymsp[-9].minor.yy539 ){
- yymsp[-9].minor.yy539->pWinDefn = yymsp[-2].minor.yy303;
+ yymsp[-9].minor.yy47 = sqlcipher_sqlite3SelectNew(pParse,yymsp[-7].minor.yy322,yymsp[-6].minor.yy131,yymsp[-5].minor.yy528,yymsp[-4].minor.yy322,yymsp[-3].minor.yy528,yymsp[-1].minor.yy322,yymsp[-8].minor.yy394,yymsp[0].minor.yy528);
+ if( yymsp[-9].minor.yy47 ){
+ yymsp[-9].minor.yy47->pWinDefn = yymsp[-2].minor.yy41;
}else{
- sqlcipher_sqlite3WindowListDelete(pParse->db, yymsp[-2].minor.yy303);
+ sqlcipher_sqlite3WindowListDelete(pParse->db, yymsp[-2].minor.yy41);
}
}
break;
- case 92: /* values ::= VALUES LP nexprlist RP */
+ case 94: /* values ::= VALUES LP nexprlist RP */
{
- yymsp[-3].minor.yy539 = sqlcipher_sqlite3SelectNew(pParse,yymsp[-1].minor.yy242,0,0,0,0,0,SF_Values,0);
+ yymsp[-3].minor.yy47 = sqlcipher_sqlite3SelectNew(pParse,yymsp[-1].minor.yy322,0,0,0,0,0,SF_Values,0);
}
break;
- case 93: /* values ::= values COMMA LP nexprlist RP */
+ case 95: /* values ::= values COMMA LP nexprlist RP */
{
- Select *pRight, *pLeft = yymsp[-4].minor.yy539;
- pRight = sqlcipher_sqlite3SelectNew(pParse,yymsp[-1].minor.yy242,0,0,0,0,0,SF_Values|SF_MultiValue,0);
+ Select *pRight, *pLeft = yymsp[-4].minor.yy47;
+ pRight = sqlcipher_sqlite3SelectNew(pParse,yymsp[-1].minor.yy322,0,0,0,0,0,SF_Values|SF_MultiValue,0);
if( ALWAYS(pLeft) ) pLeft->selFlags &= ~SF_MultiValue;
if( pRight ){
pRight->op = TK_ALL;
pRight->pPrior = pLeft;
- yymsp[-4].minor.yy539 = pRight;
+ yymsp[-4].minor.yy47 = pRight;
}else{
- yymsp[-4].minor.yy539 = pLeft;
+ yymsp[-4].minor.yy47 = pLeft;
}
}
break;
- case 94: /* distinct ::= DISTINCT */
-{yymsp[0].minor.yy192 = SF_Distinct;}
+ case 96: /* distinct ::= DISTINCT */
+{yymsp[0].minor.yy394 = SF_Distinct;}
break;
- case 95: /* distinct ::= ALL */
-{yymsp[0].minor.yy192 = SF_All;}
+ case 97: /* distinct ::= ALL */
+{yymsp[0].minor.yy394 = SF_All;}
break;
- case 97: /* sclp ::= */
- case 130: /* orderby_opt ::= */ yytestcase(yyruleno==130);
- case 140: /* groupby_opt ::= */ yytestcase(yyruleno==140);
- case 220: /* exprlist ::= */ yytestcase(yyruleno==220);
- case 223: /* paren_exprlist ::= */ yytestcase(yyruleno==223);
- case 228: /* eidlist_opt ::= */ yytestcase(yyruleno==228);
-{yymsp[1].minor.yy242 = 0;}
+ case 99: /* sclp ::= */
+ case 132: /* orderby_opt ::= */ yytestcase(yyruleno==132);
+ case 142: /* groupby_opt ::= */ yytestcase(yyruleno==142);
+ case 232: /* exprlist ::= */ yytestcase(yyruleno==232);
+ case 235: /* paren_exprlist ::= */ yytestcase(yyruleno==235);
+ case 240: /* eidlist_opt ::= */ yytestcase(yyruleno==240);
+{yymsp[1].minor.yy322 = 0;}
break;
- case 98: /* selcollist ::= sclp scanpt expr scanpt as */
+ case 100: /* selcollist ::= sclp scanpt expr scanpt as */
{
- yymsp[-4].minor.yy242 = sqlcipher_sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy242, yymsp[-2].minor.yy202);
- if( yymsp[0].minor.yy0.n>0 ) sqlcipher_sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy242, &yymsp[0].minor.yy0, 1);
- sqlcipher_sqlite3ExprListSetSpan(pParse,yymsp[-4].minor.yy242,yymsp[-3].minor.yy436,yymsp[-1].minor.yy436);
+ yymsp[-4].minor.yy322 = sqlcipher_sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy322, yymsp[-2].minor.yy528);
+ if( yymsp[0].minor.yy0.n>0 ) sqlcipher_sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy322, &yymsp[0].minor.yy0, 1);
+ sqlcipher_sqlite3ExprListSetSpan(pParse,yymsp[-4].minor.yy322,yymsp[-3].minor.yy522,yymsp[-1].minor.yy522);
}
break;
- case 99: /* selcollist ::= sclp scanpt STAR */
+ case 101: /* selcollist ::= sclp scanpt STAR */
{
Expr *p = sqlcipher_sqlite3Expr(pParse->db, TK_ASTERISK, 0);
- yymsp[-2].minor.yy242 = sqlcipher_sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy242, p);
+ yymsp[-2].minor.yy322 = sqlcipher_sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy322, p);
}
break;
- case 100: /* selcollist ::= sclp scanpt nm DOT STAR */
+ case 102: /* selcollist ::= sclp scanpt nm DOT STAR */
{
Expr *pRight = sqlcipher_sqlite3PExpr(pParse, TK_ASTERISK, 0, 0);
- Expr *pLeft = sqlcipher_sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1);
+ Expr *pLeft = tokenExpr(pParse, TK_ID, yymsp[-2].minor.yy0);
Expr *pDot = sqlcipher_sqlite3PExpr(pParse, TK_DOT, pLeft, pRight);
- yymsp[-4].minor.yy242 = sqlcipher_sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy242, pDot);
+ yymsp[-4].minor.yy322 = sqlcipher_sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy322, pDot);
}
break;
- case 101: /* as ::= AS nm */
- case 112: /* dbnm ::= DOT nm */ yytestcase(yyruleno==112);
- case 244: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==244);
- case 245: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==245);
+ case 103: /* as ::= AS nm */
+ case 115: /* dbnm ::= DOT nm */ yytestcase(yyruleno==115);
+ case 256: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==256);
+ case 257: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==257);
{yymsp[-1].minor.yy0 = yymsp[0].minor.yy0;}
break;
- case 103: /* from ::= */
- case 106: /* stl_prefix ::= */ yytestcase(yyruleno==106);
-{yymsp[1].minor.yy47 = 0;}
+ case 105: /* from ::= */
+ case 108: /* stl_prefix ::= */ yytestcase(yyruleno==108);
+{yymsp[1].minor.yy131 = 0;}
break;
- case 104: /* from ::= FROM seltablist */
+ case 106: /* from ::= FROM seltablist */
{
- yymsp[-1].minor.yy47 = yymsp[0].minor.yy47;
- sqlcipher_sqlite3SrcListShiftJoinType(yymsp[-1].minor.yy47);
+ yymsp[-1].minor.yy131 = yymsp[0].minor.yy131;
+ sqlcipher_sqlite3SrcListShiftJoinType(pParse,yymsp[-1].minor.yy131);
}
break;
- case 105: /* stl_prefix ::= seltablist joinop */
+ case 107: /* stl_prefix ::= seltablist joinop */
{
- if( ALWAYS(yymsp[-1].minor.yy47 && yymsp[-1].minor.yy47->nSrc>0) ) yymsp[-1].minor.yy47->a[yymsp[-1].minor.yy47->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy192;
+ if( ALWAYS(yymsp[-1].minor.yy131 && yymsp[-1].minor.yy131->nSrc>0) ) yymsp[-1].minor.yy131->a[yymsp[-1].minor.yy131->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy394;
}
break;
- case 107: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
+ case 109: /* seltablist ::= stl_prefix nm dbnm as on_using */
{
- yymsp[-6].minor.yy47 = sqlcipher_sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy47,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy202,yymsp[0].minor.yy600);
- sqlcipher_sqlite3SrcListIndexedBy(pParse, yymsp[-6].minor.yy47, &yymsp[-2].minor.yy0);
+ yymsp[-4].minor.yy131 = sqlcipher_sqlite3SrcListAppendFromTerm(pParse,yymsp[-4].minor.yy131,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy561);
}
break;
- case 108: /* seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */
+ case 110: /* seltablist ::= stl_prefix nm dbnm as indexed_by on_using */
{
- yymsp[-8].minor.yy47 = sqlcipher_sqlite3SrcListAppendFromTerm(pParse,yymsp[-8].minor.yy47,&yymsp[-7].minor.yy0,&yymsp[-6].minor.yy0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy202,yymsp[0].minor.yy600);
- sqlcipher_sqlite3SrcListFuncArgs(pParse, yymsp[-8].minor.yy47, yymsp[-4].minor.yy242);
+ yymsp[-5].minor.yy131 = sqlcipher_sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy131,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,0,&yymsp[0].minor.yy561);
+ sqlcipher_sqlite3SrcListIndexedBy(pParse, yymsp[-5].minor.yy131, &yymsp[-1].minor.yy0);
}
break;
- case 109: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */
+ case 111: /* seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_using */
{
- yymsp[-6].minor.yy47 = sqlcipher_sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy47,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy539,yymsp[-1].minor.yy202,yymsp[0].minor.yy600);
+ yymsp[-7].minor.yy131 = sqlcipher_sqlite3SrcListAppendFromTerm(pParse,yymsp[-7].minor.yy131,&yymsp[-6].minor.yy0,&yymsp[-5].minor.yy0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy561);
+ sqlcipher_sqlite3SrcListFuncArgs(pParse, yymsp[-7].minor.yy131, yymsp[-3].minor.yy322);
+}
+ break;
+ case 112: /* seltablist ::= stl_prefix LP select RP as on_using */
+{
+ yymsp[-5].minor.yy131 = sqlcipher_sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy131,0,0,&yymsp[-1].minor.yy0,yymsp[-3].minor.yy47,&yymsp[0].minor.yy561);
}
break;
- case 110: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
+ case 113: /* seltablist ::= stl_prefix LP seltablist RP as on_using */
{
- if( yymsp[-6].minor.yy47==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy202==0 && yymsp[0].minor.yy600==0 ){
- yymsp[-6].minor.yy47 = yymsp[-4].minor.yy47;
- }else if( yymsp[-4].minor.yy47->nSrc==1 ){
- yymsp[-6].minor.yy47 = sqlcipher_sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy47,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy202,yymsp[0].minor.yy600);
- if( yymsp[-6].minor.yy47 ){
- struct SrcList_item *pNew = &yymsp[-6].minor.yy47->a[yymsp[-6].minor.yy47->nSrc-1];
- struct SrcList_item *pOld = yymsp[-4].minor.yy47->a;
+ if( yymsp[-5].minor.yy131==0 && yymsp[-1].minor.yy0.n==0 && yymsp[0].minor.yy561.pOn==0 && yymsp[0].minor.yy561.pUsing==0 ){
+ yymsp[-5].minor.yy131 = yymsp[-3].minor.yy131;
+ }else if( yymsp[-3].minor.yy131->nSrc==1 ){
+ yymsp[-5].minor.yy131 = sqlcipher_sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy131,0,0,&yymsp[-1].minor.yy0,0,&yymsp[0].minor.yy561);
+ if( yymsp[-5].minor.yy131 ){
+ SrcItem *pNew = &yymsp[-5].minor.yy131->a[yymsp[-5].minor.yy131->nSrc-1];
+ SrcItem *pOld = yymsp[-3].minor.yy131->a;
pNew->zName = pOld->zName;
pNew->zDatabase = pOld->zDatabase;
pNew->pSelect = pOld->pSelect;
+ if( pNew->pSelect && (pNew->pSelect->selFlags & SF_NestedFrom)!=0 ){
+ pNew->fg.isNestedFrom = 1;
+ }
if( pOld->fg.isTabFunc ){
pNew->u1.pFuncArg = pOld->u1.pFuncArg;
pOld->u1.pFuncArg = 0;
@@ -163702,264 +172953,291 @@ static YYACTIONTYPE yy_reduce(
pOld->zName = pOld->zDatabase = 0;
pOld->pSelect = 0;
}
- sqlcipher_sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy47);
+ sqlcipher_sqlite3SrcListDelete(pParse->db, yymsp[-3].minor.yy131);
}else{
Select *pSubquery;
- sqlcipher_sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy47);
- pSubquery = sqlcipher_sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy47,0,0,0,0,SF_NestedFrom,0);
- yymsp[-6].minor.yy47 = sqlcipher_sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy47,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy202,yymsp[0].minor.yy600);
+ sqlcipher_sqlite3SrcListShiftJoinType(pParse,yymsp[-3].minor.yy131);
+ pSubquery = sqlcipher_sqlite3SelectNew(pParse,0,yymsp[-3].minor.yy131,0,0,0,0,SF_NestedFrom,0);
+ yymsp[-5].minor.yy131 = sqlcipher_sqlite3SrcListAppendFromTerm(pParse,yymsp[-5].minor.yy131,0,0,&yymsp[-1].minor.yy0,pSubquery,&yymsp[0].minor.yy561);
}
}
break;
- case 111: /* dbnm ::= */
- case 125: /* indexed_opt ::= */ yytestcase(yyruleno==125);
+ case 114: /* dbnm ::= */
+ case 129: /* indexed_opt ::= */ yytestcase(yyruleno==129);
{yymsp[1].minor.yy0.z=0; yymsp[1].minor.yy0.n=0;}
break;
- case 113: /* fullname ::= nm */
+ case 116: /* fullname ::= nm */
{
- yylhsminor.yy47 = sqlcipher_sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0);
- if( IN_RENAME_OBJECT && yylhsminor.yy47 ) sqlcipher_sqlite3RenameTokenMap(pParse, yylhsminor.yy47->a[0].zName, &yymsp[0].minor.yy0);
+ yylhsminor.yy131 = sqlcipher_sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0);
+ if( IN_RENAME_OBJECT && yylhsminor.yy131 ) sqlcipher_sqlite3RenameTokenMap(pParse, yylhsminor.yy131->a[0].zName, &yymsp[0].minor.yy0);
}
- yymsp[0].minor.yy47 = yylhsminor.yy47;
+ yymsp[0].minor.yy131 = yylhsminor.yy131;
break;
- case 114: /* fullname ::= nm DOT nm */
+ case 117: /* fullname ::= nm DOT nm */
{
- yylhsminor.yy47 = sqlcipher_sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
- if( IN_RENAME_OBJECT && yylhsminor.yy47 ) sqlcipher_sqlite3RenameTokenMap(pParse, yylhsminor.yy47->a[0].zName, &yymsp[0].minor.yy0);
+ yylhsminor.yy131 = sqlcipher_sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
+ if( IN_RENAME_OBJECT && yylhsminor.yy131 ) sqlcipher_sqlite3RenameTokenMap(pParse, yylhsminor.yy131->a[0].zName, &yymsp[0].minor.yy0);
}
- yymsp[-2].minor.yy47 = yylhsminor.yy47;
+ yymsp[-2].minor.yy131 = yylhsminor.yy131;
break;
- case 115: /* xfullname ::= nm */
-{yymsp[0].minor.yy47 = sqlcipher_sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0); /*A-overwrites-X*/}
+ case 118: /* xfullname ::= nm */
+{yymsp[0].minor.yy131 = sqlcipher_sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0); /*A-overwrites-X*/}
break;
- case 116: /* xfullname ::= nm DOT nm */
-{yymsp[-2].minor.yy47 = sqlcipher_sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/}
+ case 119: /* xfullname ::= nm DOT nm */
+{yymsp[-2].minor.yy131 = sqlcipher_sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/}
break;
- case 117: /* xfullname ::= nm DOT nm AS nm */
+ case 120: /* xfullname ::= nm DOT nm AS nm */
{
- yymsp[-4].minor.yy47 = sqlcipher_sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,&yymsp[-2].minor.yy0); /*A-overwrites-X*/
- if( yymsp[-4].minor.yy47 ) yymsp[-4].minor.yy47->a[0].zAlias = sqlcipher_sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0);
+ yymsp[-4].minor.yy131 = sqlcipher_sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,&yymsp[-2].minor.yy0); /*A-overwrites-X*/
+ if( yymsp[-4].minor.yy131 ) yymsp[-4].minor.yy131->a[0].zAlias = sqlcipher_sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0);
}
break;
- case 118: /* xfullname ::= nm AS nm */
+ case 121: /* xfullname ::= nm AS nm */
{
- yymsp[-2].minor.yy47 = sqlcipher_sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,0); /*A-overwrites-X*/
- if( yymsp[-2].minor.yy47 ) yymsp[-2].minor.yy47->a[0].zAlias = sqlcipher_sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0);
+ yymsp[-2].minor.yy131 = sqlcipher_sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,0); /*A-overwrites-X*/
+ if( yymsp[-2].minor.yy131 ) yymsp[-2].minor.yy131->a[0].zAlias = sqlcipher_sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0);
}
break;
- case 119: /* joinop ::= COMMA|JOIN */
-{ yymsp[0].minor.yy192 = JT_INNER; }
+ case 122: /* joinop ::= COMMA|JOIN */
+{ yymsp[0].minor.yy394 = JT_INNER; }
break;
- case 120: /* joinop ::= JOIN_KW JOIN */
-{yymsp[-1].minor.yy192 = sqlcipher_sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/}
+ case 123: /* joinop ::= JOIN_KW JOIN */
+{yymsp[-1].minor.yy394 = sqlcipher_sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/}
break;
- case 121: /* joinop ::= JOIN_KW nm JOIN */
-{yymsp[-2].minor.yy192 = sqlcipher_sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/}
+ case 124: /* joinop ::= JOIN_KW nm JOIN */
+{yymsp[-2].minor.yy394 = sqlcipher_sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/}
break;
- case 122: /* joinop ::= JOIN_KW nm nm JOIN */
-{yymsp[-3].minor.yy192 = sqlcipher_sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/}
+ case 125: /* joinop ::= JOIN_KW nm nm JOIN */
+{yymsp[-3].minor.yy394 = sqlcipher_sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/}
break;
- case 123: /* on_opt ::= ON expr */
- case 143: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==143);
- case 150: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==150);
- case 216: /* case_else ::= ELSE expr */ yytestcase(yyruleno==216);
- case 237: /* vinto ::= INTO expr */ yytestcase(yyruleno==237);
-{yymsp[-1].minor.yy202 = yymsp[0].minor.yy202;}
+ case 126: /* on_using ::= ON expr */
+{yymsp[-1].minor.yy561.pOn = yymsp[0].minor.yy528; yymsp[-1].minor.yy561.pUsing = 0;}
break;
- case 124: /* on_opt ::= */
- case 142: /* having_opt ::= */ yytestcase(yyruleno==142);
- case 144: /* limit_opt ::= */ yytestcase(yyruleno==144);
- case 149: /* where_opt ::= */ yytestcase(yyruleno==149);
- case 217: /* case_else ::= */ yytestcase(yyruleno==217);
- case 219: /* case_operand ::= */ yytestcase(yyruleno==219);
- case 238: /* vinto ::= */ yytestcase(yyruleno==238);
-{yymsp[1].minor.yy202 = 0;}
+ case 127: /* on_using ::= USING LP idlist RP */
+{yymsp[-3].minor.yy561.pOn = 0; yymsp[-3].minor.yy561.pUsing = yymsp[-1].minor.yy254;}
break;
- case 126: /* indexed_opt ::= INDEXED BY nm */
+ case 128: /* on_using ::= */
+{yymsp[1].minor.yy561.pOn = 0; yymsp[1].minor.yy561.pUsing = 0;}
+ break;
+ case 130: /* indexed_by ::= INDEXED BY nm */
{yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;}
break;
- case 127: /* indexed_opt ::= NOT INDEXED */
+ case 131: /* indexed_by ::= NOT INDEXED */
{yymsp[-1].minor.yy0.z=0; yymsp[-1].minor.yy0.n=1;}
break;
- case 128: /* using_opt ::= USING LP idlist RP */
-{yymsp[-3].minor.yy600 = yymsp[-1].minor.yy600;}
- break;
- case 129: /* using_opt ::= */
- case 164: /* idlist_opt ::= */ yytestcase(yyruleno==164);
-{yymsp[1].minor.yy600 = 0;}
+ case 133: /* orderby_opt ::= ORDER BY sortlist */
+ case 143: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==143);
+{yymsp[-2].minor.yy322 = yymsp[0].minor.yy322;}
break;
- case 131: /* orderby_opt ::= ORDER BY sortlist */
- case 141: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==141);
-{yymsp[-2].minor.yy242 = yymsp[0].minor.yy242;}
- break;
- case 132: /* sortlist ::= sortlist COMMA expr sortorder nulls */
+ case 134: /* sortlist ::= sortlist COMMA expr sortorder nulls */
{
- yymsp[-4].minor.yy242 = sqlcipher_sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy242,yymsp[-2].minor.yy202);
- sqlcipher_sqlite3ExprListSetSortOrder(yymsp[-4].minor.yy242,yymsp[-1].minor.yy192,yymsp[0].minor.yy192);
+ yymsp[-4].minor.yy322 = sqlcipher_sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy322,yymsp[-2].minor.yy528);
+ sqlcipher_sqlite3ExprListSetSortOrder(yymsp[-4].minor.yy322,yymsp[-1].minor.yy394,yymsp[0].minor.yy394);
}
break;
- case 133: /* sortlist ::= expr sortorder nulls */
+ case 135: /* sortlist ::= expr sortorder nulls */
{
- yymsp[-2].minor.yy242 = sqlcipher_sqlite3ExprListAppend(pParse,0,yymsp[-2].minor.yy202); /*A-overwrites-Y*/
- sqlcipher_sqlite3ExprListSetSortOrder(yymsp[-2].minor.yy242,yymsp[-1].minor.yy192,yymsp[0].minor.yy192);
+ yymsp[-2].minor.yy322 = sqlcipher_sqlite3ExprListAppend(pParse,0,yymsp[-2].minor.yy528); /*A-overwrites-Y*/
+ sqlcipher_sqlite3ExprListSetSortOrder(yymsp[-2].minor.yy322,yymsp[-1].minor.yy394,yymsp[0].minor.yy394);
}
break;
- case 134: /* sortorder ::= ASC */
-{yymsp[0].minor.yy192 = SQLITE_SO_ASC;}
+ case 136: /* sortorder ::= ASC */
+{yymsp[0].minor.yy394 = SQLITE_SO_ASC;}
+ break;
+ case 137: /* sortorder ::= DESC */
+{yymsp[0].minor.yy394 = SQLITE_SO_DESC;}
+ break;
+ case 138: /* sortorder ::= */
+ case 141: /* nulls ::= */ yytestcase(yyruleno==141);
+{yymsp[1].minor.yy394 = SQLITE_SO_UNDEFINED;}
break;
- case 135: /* sortorder ::= DESC */
-{yymsp[0].minor.yy192 = SQLITE_SO_DESC;}
+ case 139: /* nulls ::= NULLS FIRST */
+{yymsp[-1].minor.yy394 = SQLITE_SO_ASC;}
break;
- case 136: /* sortorder ::= */
- case 139: /* nulls ::= */ yytestcase(yyruleno==139);
-{yymsp[1].minor.yy192 = SQLITE_SO_UNDEFINED;}
+ case 140: /* nulls ::= NULLS LAST */
+{yymsp[-1].minor.yy394 = SQLITE_SO_DESC;}
break;
- case 137: /* nulls ::= NULLS FIRST */
-{yymsp[-1].minor.yy192 = SQLITE_SO_ASC;}
+ case 144: /* having_opt ::= */
+ case 146: /* limit_opt ::= */ yytestcase(yyruleno==146);
+ case 151: /* where_opt ::= */ yytestcase(yyruleno==151);
+ case 153: /* where_opt_ret ::= */ yytestcase(yyruleno==153);
+ case 229: /* case_else ::= */ yytestcase(yyruleno==229);
+ case 231: /* case_operand ::= */ yytestcase(yyruleno==231);
+ case 250: /* vinto ::= */ yytestcase(yyruleno==250);
+{yymsp[1].minor.yy528 = 0;}
break;
- case 138: /* nulls ::= NULLS LAST */
-{yymsp[-1].minor.yy192 = SQLITE_SO_DESC;}
+ case 145: /* having_opt ::= HAVING expr */
+ case 152: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==152);
+ case 154: /* where_opt_ret ::= WHERE expr */ yytestcase(yyruleno==154);
+ case 228: /* case_else ::= ELSE expr */ yytestcase(yyruleno==228);
+ case 249: /* vinto ::= INTO expr */ yytestcase(yyruleno==249);
+{yymsp[-1].minor.yy528 = yymsp[0].minor.yy528;}
break;
- case 145: /* limit_opt ::= LIMIT expr */
-{yymsp[-1].minor.yy202 = sqlcipher_sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy202,0);}
+ case 147: /* limit_opt ::= LIMIT expr */
+{yymsp[-1].minor.yy528 = sqlcipher_sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy528,0);}
break;
- case 146: /* limit_opt ::= LIMIT expr OFFSET expr */
-{yymsp[-3].minor.yy202 = sqlcipher_sqlite3PExpr(pParse,TK_LIMIT,yymsp[-2].minor.yy202,yymsp[0].minor.yy202);}
+ case 148: /* limit_opt ::= LIMIT expr OFFSET expr */
+{yymsp[-3].minor.yy528 = sqlcipher_sqlite3PExpr(pParse,TK_LIMIT,yymsp[-2].minor.yy528,yymsp[0].minor.yy528);}
break;
- case 147: /* limit_opt ::= LIMIT expr COMMA expr */
-{yymsp[-3].minor.yy202 = sqlcipher_sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy202,yymsp[-2].minor.yy202);}
+ case 149: /* limit_opt ::= LIMIT expr COMMA expr */
+{yymsp[-3].minor.yy528 = sqlcipher_sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy528,yymsp[-2].minor.yy528);}
break;
- case 148: /* cmd ::= with DELETE FROM xfullname indexed_opt where_opt orderby_opt limit_opt */
+ case 150: /* cmd ::= with DELETE FROM xfullname indexed_opt where_opt_ret orderby_opt limit_opt */
{
- sqlcipher_sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy47, &yymsp[-3].minor.yy0);
+ sqlcipher_sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy131, &yymsp[-3].minor.yy0);
#ifndef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
- if( yymsp[-1].minor.yy242 || yymsp[0].minor.yy202 ){
- updateDeleteLimitError(pParse,yymsp[-1].minor.yy242,yymsp[0].minor.yy202);
- yymsp[-1].minor.yy242 = 0;
- yymsp[0].minor.yy202 = 0;
+ if( yymsp[-1].minor.yy322 || yymsp[0].minor.yy528 ){
+ updateDeleteLimitError(pParse,yymsp[-1].minor.yy322,yymsp[0].minor.yy528);
+ yymsp[-1].minor.yy322 = 0;
+ yymsp[0].minor.yy528 = 0;
}
#endif
- sqlcipher_sqlite3DeleteFrom(pParse,yymsp[-4].minor.yy47,yymsp[-2].minor.yy202,yymsp[-1].minor.yy242,yymsp[0].minor.yy202);
+ sqlcipher_sqlite3DeleteFrom(pParse,yymsp[-4].minor.yy131,yymsp[-2].minor.yy528,yymsp[-1].minor.yy322,yymsp[0].minor.yy528);
}
break;
- case 151: /* cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt orderby_opt limit_opt */
+ case 155: /* where_opt_ret ::= RETURNING selcollist */
+{sqlcipher_sqlite3AddReturning(pParse,yymsp[0].minor.yy322); yymsp[-1].minor.yy528 = 0;}
+ break;
+ case 156: /* where_opt_ret ::= WHERE expr RETURNING selcollist */
+{sqlcipher_sqlite3AddReturning(pParse,yymsp[0].minor.yy322); yymsp[-3].minor.yy528 = yymsp[-2].minor.yy528;}
+ break;
+ case 157: /* cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist from where_opt_ret orderby_opt limit_opt */
{
- sqlcipher_sqlite3SrcListIndexedBy(pParse, yymsp[-7].minor.yy47, &yymsp[-6].minor.yy0);
- yymsp[-7].minor.yy47 = sqlcipher_sqlite3SrcListAppendList(pParse, yymsp[-7].minor.yy47, yymsp[-3].minor.yy47);
- sqlcipher_sqlite3ExprListCheckLength(pParse,yymsp[-4].minor.yy242,"set list");
+ sqlcipher_sqlite3SrcListIndexedBy(pParse, yymsp[-7].minor.yy131, &yymsp[-6].minor.yy0);
+ if( yymsp[-3].minor.yy131 ){
+ SrcList *pFromClause = yymsp[-3].minor.yy131;
+ if( pFromClause->nSrc>1 ){
+ Select *pSubquery;
+ Token as;
+ pSubquery = sqlcipher_sqlite3SelectNew(pParse,0,pFromClause,0,0,0,0,SF_NestedFrom,0);
+ as.n = 0;
+ as.z = 0;
+ pFromClause = sqlcipher_sqlite3SrcListAppendFromTerm(pParse,0,0,0,&as,pSubquery,0);
+ }
+ yymsp[-7].minor.yy131 = sqlcipher_sqlite3SrcListAppendList(pParse, yymsp[-7].minor.yy131, pFromClause);
+ }
+ sqlcipher_sqlite3ExprListCheckLength(pParse,yymsp[-4].minor.yy322,"set list");
#ifndef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
- if( yymsp[-1].minor.yy242 || yymsp[0].minor.yy202 ){
- updateDeleteLimitError(pParse,yymsp[-1].minor.yy242,yymsp[0].minor.yy202);
- yymsp[-1].minor.yy242 = 0;
- yymsp[0].minor.yy202 = 0;
+ if( yymsp[-1].minor.yy322 || yymsp[0].minor.yy528 ){
+ updateDeleteLimitError(pParse,yymsp[-1].minor.yy322,yymsp[0].minor.yy528);
+ yymsp[-1].minor.yy322 = 0;
+ yymsp[0].minor.yy528 = 0;
}
#endif
- sqlcipher_sqlite3Update(pParse,yymsp[-7].minor.yy47,yymsp[-4].minor.yy242,yymsp[-2].minor.yy202,yymsp[-8].minor.yy192,yymsp[-1].minor.yy242,yymsp[0].minor.yy202,0);
+ sqlcipher_sqlite3Update(pParse,yymsp[-7].minor.yy131,yymsp[-4].minor.yy322,yymsp[-2].minor.yy528,yymsp[-8].minor.yy394,yymsp[-1].minor.yy322,yymsp[0].minor.yy528,0);
}
break;
- case 152: /* setlist ::= setlist COMMA nm EQ expr */
+ case 158: /* setlist ::= setlist COMMA nm EQ expr */
{
- yymsp[-4].minor.yy242 = sqlcipher_sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy242, yymsp[0].minor.yy202);
- sqlcipher_sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy242, &yymsp[-2].minor.yy0, 1);
+ yymsp[-4].minor.yy322 = sqlcipher_sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy322, yymsp[0].minor.yy528);
+ sqlcipher_sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy322, &yymsp[-2].minor.yy0, 1);
}
break;
- case 153: /* setlist ::= setlist COMMA LP idlist RP EQ expr */
+ case 159: /* setlist ::= setlist COMMA LP idlist RP EQ expr */
{
- yymsp[-6].minor.yy242 = sqlcipher_sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy242, yymsp[-3].minor.yy600, yymsp[0].minor.yy202);
+ yymsp[-6].minor.yy322 = sqlcipher_sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy322, yymsp[-3].minor.yy254, yymsp[0].minor.yy528);
}
break;
- case 154: /* setlist ::= nm EQ expr */
+ case 160: /* setlist ::= nm EQ expr */
{
- yylhsminor.yy242 = sqlcipher_sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy202);
- sqlcipher_sqlite3ExprListSetName(pParse, yylhsminor.yy242, &yymsp[-2].minor.yy0, 1);
+ yylhsminor.yy322 = sqlcipher_sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy528);
+ sqlcipher_sqlite3ExprListSetName(pParse, yylhsminor.yy322, &yymsp[-2].minor.yy0, 1);
}
- yymsp[-2].minor.yy242 = yylhsminor.yy242;
+ yymsp[-2].minor.yy322 = yylhsminor.yy322;
break;
- case 155: /* setlist ::= LP idlist RP EQ expr */
+ case 161: /* setlist ::= LP idlist RP EQ expr */
{
- yymsp[-4].minor.yy242 = sqlcipher_sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy600, yymsp[0].minor.yy202);
+ yymsp[-4].minor.yy322 = sqlcipher_sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy254, yymsp[0].minor.yy528);
}
break;
- case 156: /* cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */
+ case 162: /* cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */
{
- sqlcipher_sqlite3Insert(pParse, yymsp[-3].minor.yy47, yymsp[-1].minor.yy539, yymsp[-2].minor.yy600, yymsp[-5].minor.yy192, yymsp[0].minor.yy318);
+ sqlcipher_sqlite3Insert(pParse, yymsp[-3].minor.yy131, yymsp[-1].minor.yy47, yymsp[-2].minor.yy254, yymsp[-5].minor.yy394, yymsp[0].minor.yy444);
}
break;
- case 157: /* cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES */
+ case 163: /* cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES returning */
{
- sqlcipher_sqlite3Insert(pParse, yymsp[-3].minor.yy47, 0, yymsp[-2].minor.yy600, yymsp[-5].minor.yy192, 0);
+ sqlcipher_sqlite3Insert(pParse, yymsp[-4].minor.yy131, 0, yymsp[-3].minor.yy254, yymsp[-6].minor.yy394, 0);
}
break;
- case 158: /* upsert ::= */
-{ yymsp[1].minor.yy318 = 0; }
+ case 164: /* upsert ::= */
+{ yymsp[1].minor.yy444 = 0; }
+ break;
+ case 165: /* upsert ::= RETURNING selcollist */
+{ yymsp[-1].minor.yy444 = 0; sqlcipher_sqlite3AddReturning(pParse,yymsp[0].minor.yy322); }
break;
- case 159: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt */
-{ yymsp[-10].minor.yy318 = sqlcipher_sqlite3UpsertNew(pParse->db,yymsp[-7].minor.yy242,yymsp[-5].minor.yy202,yymsp[-1].minor.yy242,yymsp[0].minor.yy202);}
+ case 166: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt upsert */
+{ yymsp[-11].minor.yy444 = sqlcipher_sqlite3UpsertNew(pParse->db,yymsp[-8].minor.yy322,yymsp[-6].minor.yy528,yymsp[-2].minor.yy322,yymsp[-1].minor.yy528,yymsp[0].minor.yy444);}
break;
- case 160: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING */
-{ yymsp[-7].minor.yy318 = sqlcipher_sqlite3UpsertNew(pParse->db,yymsp[-4].minor.yy242,yymsp[-2].minor.yy202,0,0); }
+ case 167: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING upsert */
+{ yymsp[-8].minor.yy444 = sqlcipher_sqlite3UpsertNew(pParse->db,yymsp[-5].minor.yy322,yymsp[-3].minor.yy528,0,0,yymsp[0].minor.yy444); }
break;
- case 161: /* upsert ::= ON CONFLICT DO NOTHING */
-{ yymsp[-3].minor.yy318 = sqlcipher_sqlite3UpsertNew(pParse->db,0,0,0,0); }
+ case 168: /* upsert ::= ON CONFLICT DO NOTHING returning */
+{ yymsp[-4].minor.yy444 = sqlcipher_sqlite3UpsertNew(pParse->db,0,0,0,0,0); }
break;
- case 165: /* idlist_opt ::= LP idlist RP */
-{yymsp[-2].minor.yy600 = yymsp[-1].minor.yy600;}
+ case 169: /* upsert ::= ON CONFLICT DO UPDATE SET setlist where_opt returning */
+{ yymsp[-7].minor.yy444 = sqlcipher_sqlite3UpsertNew(pParse->db,0,0,yymsp[-2].minor.yy322,yymsp[-1].minor.yy528,0);}
break;
- case 166: /* idlist ::= idlist COMMA nm */
-{yymsp[-2].minor.yy600 = sqlcipher_sqlite3IdListAppend(pParse,yymsp[-2].minor.yy600,&yymsp[0].minor.yy0);}
+ case 170: /* returning ::= RETURNING selcollist */
+{sqlcipher_sqlite3AddReturning(pParse,yymsp[0].minor.yy322);}
break;
- case 167: /* idlist ::= nm */
-{yymsp[0].minor.yy600 = sqlcipher_sqlite3IdListAppend(pParse,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/}
+ case 173: /* idlist_opt ::= */
+{yymsp[1].minor.yy254 = 0;}
break;
- case 168: /* expr ::= LP expr RP */
-{yymsp[-2].minor.yy202 = yymsp[-1].minor.yy202;}
+ case 174: /* idlist_opt ::= LP idlist RP */
+{yymsp[-2].minor.yy254 = yymsp[-1].minor.yy254;}
break;
- case 169: /* expr ::= ID|INDEXED */
- case 170: /* expr ::= JOIN_KW */ yytestcase(yyruleno==170);
-{yymsp[0].minor.yy202=tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/}
+ case 175: /* idlist ::= idlist COMMA nm */
+{yymsp[-2].minor.yy254 = sqlcipher_sqlite3IdListAppend(pParse,yymsp[-2].minor.yy254,&yymsp[0].minor.yy0);}
break;
- case 171: /* expr ::= nm DOT nm */
+ case 176: /* idlist ::= nm */
+{yymsp[0].minor.yy254 = sqlcipher_sqlite3IdListAppend(pParse,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/}
+ break;
+ case 177: /* expr ::= LP expr RP */
+{yymsp[-2].minor.yy528 = yymsp[-1].minor.yy528;}
+ break;
+ case 178: /* expr ::= ID|INDEXED */
+ case 179: /* expr ::= JOIN_KW */ yytestcase(yyruleno==179);
+{yymsp[0].minor.yy528=tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/}
+ break;
+ case 180: /* expr ::= nm DOT nm */
{
- Expr *temp1 = sqlcipher_sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1);
- Expr *temp2 = sqlcipher_sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[0].minor.yy0, 1);
- if( IN_RENAME_OBJECT ){
- sqlcipher_sqlite3RenameTokenMap(pParse, (void*)temp2, &yymsp[0].minor.yy0);
- sqlcipher_sqlite3RenameTokenMap(pParse, (void*)temp1, &yymsp[-2].minor.yy0);
- }
- yylhsminor.yy202 = sqlcipher_sqlite3PExpr(pParse, TK_DOT, temp1, temp2);
+ Expr *temp1 = tokenExpr(pParse,TK_ID,yymsp[-2].minor.yy0);
+ Expr *temp2 = tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0);
+ yylhsminor.yy528 = sqlcipher_sqlite3PExpr(pParse, TK_DOT, temp1, temp2);
}
- yymsp[-2].minor.yy202 = yylhsminor.yy202;
+ yymsp[-2].minor.yy528 = yylhsminor.yy528;
break;
- case 172: /* expr ::= nm DOT nm DOT nm */
+ case 181: /* expr ::= nm DOT nm DOT nm */
{
- Expr *temp1 = sqlcipher_sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-4].minor.yy0, 1);
- Expr *temp2 = sqlcipher_sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1);
- Expr *temp3 = sqlcipher_sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[0].minor.yy0, 1);
+ Expr *temp1 = tokenExpr(pParse,TK_ID,yymsp[-4].minor.yy0);
+ Expr *temp2 = tokenExpr(pParse,TK_ID,yymsp[-2].minor.yy0);
+ Expr *temp3 = tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0);
Expr *temp4 = sqlcipher_sqlite3PExpr(pParse, TK_DOT, temp2, temp3);
if( IN_RENAME_OBJECT ){
- sqlcipher_sqlite3RenameTokenMap(pParse, (void*)temp3, &yymsp[0].minor.yy0);
- sqlcipher_sqlite3RenameTokenMap(pParse, (void*)temp2, &yymsp[-2].minor.yy0);
+ sqlcipher_sqlite3RenameTokenRemap(pParse, 0, temp1);
}
- yylhsminor.yy202 = sqlcipher_sqlite3PExpr(pParse, TK_DOT, temp1, temp4);
+ yylhsminor.yy528 = sqlcipher_sqlite3PExpr(pParse, TK_DOT, temp1, temp4);
}
- yymsp[-4].minor.yy202 = yylhsminor.yy202;
+ yymsp[-4].minor.yy528 = yylhsminor.yy528;
break;
- case 173: /* term ::= NULL|FLOAT|BLOB */
- case 174: /* term ::= STRING */ yytestcase(yyruleno==174);
-{yymsp[0].minor.yy202=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0); /*A-overwrites-X*/}
+ case 182: /* term ::= NULL|FLOAT|BLOB */
+ case 183: /* term ::= STRING */ yytestcase(yyruleno==183);
+{yymsp[0].minor.yy528=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0); /*A-overwrites-X*/}
break;
- case 175: /* term ::= INTEGER */
+ case 184: /* term ::= INTEGER */
{
- yylhsminor.yy202 = sqlcipher_sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1);
+ yylhsminor.yy528 = sqlcipher_sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1);
+ if( yylhsminor.yy528 ) yylhsminor.yy528->w.iOfst = (int)(yymsp[0].minor.yy0.z - pParse->zTail);
}
- yymsp[0].minor.yy202 = yylhsminor.yy202;
+ yymsp[0].minor.yy528 = yylhsminor.yy528;
break;
- case 176: /* expr ::= VARIABLE */
+ case 185: /* expr ::= VARIABLE */
{
if( !(yymsp[0].minor.yy0.z[0]=='#' && sqlcipher_sqlite3Isdigit(yymsp[0].minor.yy0.z[1])) ){
u32 n = yymsp[0].minor.yy0.n;
- yymsp[0].minor.yy202 = tokenExpr(pParse, TK_VARIABLE, yymsp[0].minor.yy0);
- sqlcipher_sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy202, n);
+ yymsp[0].minor.yy528 = tokenExpr(pParse, TK_VARIABLE, yymsp[0].minor.yy0);
+ sqlcipher_sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy528, n);
}else{
/* When doing a nested parse, one can include terms in an expression
** that look like this: #1 #2 ... These terms refer to registers
@@ -163968,159 +173246,179 @@ static YYACTIONTYPE yy_reduce(
assert( t.n>=2 );
if( pParse->nested==0 ){
sqlcipher_sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &t);
- yymsp[0].minor.yy202 = 0;
+ yymsp[0].minor.yy528 = 0;
}else{
- yymsp[0].minor.yy202 = sqlcipher_sqlite3PExpr(pParse, TK_REGISTER, 0, 0);
- if( yymsp[0].minor.yy202 ) sqlcipher_sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy202->iTable);
+ yymsp[0].minor.yy528 = sqlcipher_sqlite3PExpr(pParse, TK_REGISTER, 0, 0);
+ if( yymsp[0].minor.yy528 ) sqlcipher_sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy528->iTable);
}
}
}
break;
- case 177: /* expr ::= expr COLLATE ID|STRING */
+ case 186: /* expr ::= expr COLLATE ID|STRING */
{
- yymsp[-2].minor.yy202 = sqlcipher_sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy202, &yymsp[0].minor.yy0, 1);
+ yymsp[-2].minor.yy528 = sqlcipher_sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy528, &yymsp[0].minor.yy0, 1);
}
break;
- case 178: /* expr ::= CAST LP expr AS typetoken RP */
+ case 187: /* expr ::= CAST LP expr AS typetoken RP */
{
- yymsp[-5].minor.yy202 = sqlcipher_sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1);
- sqlcipher_sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy202, yymsp[-3].minor.yy202, 0);
+ yymsp[-5].minor.yy528 = sqlcipher_sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1);
+ sqlcipher_sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy528, yymsp[-3].minor.yy528, 0);
}
break;
- case 179: /* expr ::= ID|INDEXED LP distinct exprlist RP */
+ case 188: /* expr ::= ID|INDEXED LP distinct exprlist RP */
{
- yylhsminor.yy202 = sqlcipher_sqlite3ExprFunction(pParse, yymsp[-1].minor.yy242, &yymsp[-4].minor.yy0, yymsp[-2].minor.yy192);
+ yylhsminor.yy528 = sqlcipher_sqlite3ExprFunction(pParse, yymsp[-1].minor.yy322, &yymsp[-4].minor.yy0, yymsp[-2].minor.yy394);
}
- yymsp[-4].minor.yy202 = yylhsminor.yy202;
+ yymsp[-4].minor.yy528 = yylhsminor.yy528;
break;
- case 180: /* expr ::= ID|INDEXED LP STAR RP */
+ case 189: /* expr ::= ID|INDEXED LP STAR RP */
{
- yylhsminor.yy202 = sqlcipher_sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0, 0);
+ yylhsminor.yy528 = sqlcipher_sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0, 0);
}
- yymsp[-3].minor.yy202 = yylhsminor.yy202;
+ yymsp[-3].minor.yy528 = yylhsminor.yy528;
break;
- case 181: /* expr ::= ID|INDEXED LP distinct exprlist RP filter_over */
+ case 190: /* expr ::= ID|INDEXED LP distinct exprlist RP filter_over */
{
- yylhsminor.yy202 = sqlcipher_sqlite3ExprFunction(pParse, yymsp[-2].minor.yy242, &yymsp[-5].minor.yy0, yymsp[-3].minor.yy192);
- sqlcipher_sqlite3WindowAttach(pParse, yylhsminor.yy202, yymsp[0].minor.yy303);
+ yylhsminor.yy528 = sqlcipher_sqlite3ExprFunction(pParse, yymsp[-2].minor.yy322, &yymsp[-5].minor.yy0, yymsp[-3].minor.yy394);
+ sqlcipher_sqlite3WindowAttach(pParse, yylhsminor.yy528, yymsp[0].minor.yy41);
}
- yymsp[-5].minor.yy202 = yylhsminor.yy202;
+ yymsp[-5].minor.yy528 = yylhsminor.yy528;
break;
- case 182: /* expr ::= ID|INDEXED LP STAR RP filter_over */
+ case 191: /* expr ::= ID|INDEXED LP STAR RP filter_over */
{
- yylhsminor.yy202 = sqlcipher_sqlite3ExprFunction(pParse, 0, &yymsp[-4].minor.yy0, 0);
- sqlcipher_sqlite3WindowAttach(pParse, yylhsminor.yy202, yymsp[0].minor.yy303);
+ yylhsminor.yy528 = sqlcipher_sqlite3ExprFunction(pParse, 0, &yymsp[-4].minor.yy0, 0);
+ sqlcipher_sqlite3WindowAttach(pParse, yylhsminor.yy528, yymsp[0].minor.yy41);
}
- yymsp[-4].minor.yy202 = yylhsminor.yy202;
+ yymsp[-4].minor.yy528 = yylhsminor.yy528;
break;
- case 183: /* term ::= CTIME_KW */
+ case 192: /* term ::= CTIME_KW */
{
- yylhsminor.yy202 = sqlcipher_sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0, 0);
+ yylhsminor.yy528 = sqlcipher_sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0, 0);
}
- yymsp[0].minor.yy202 = yylhsminor.yy202;
+ yymsp[0].minor.yy528 = yylhsminor.yy528;
break;
- case 184: /* expr ::= LP nexprlist COMMA expr RP */
+ case 193: /* expr ::= LP nexprlist COMMA expr RP */
{
- ExprList *pList = sqlcipher_sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy242, yymsp[-1].minor.yy202);
- yymsp[-4].minor.yy202 = sqlcipher_sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
- if( yymsp[-4].minor.yy202 ){
- yymsp[-4].minor.yy202->x.pList = pList;
+ ExprList *pList = sqlcipher_sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy322, yymsp[-1].minor.yy528);
+ yymsp[-4].minor.yy528 = sqlcipher_sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
+ if( yymsp[-4].minor.yy528 ){
+ yymsp[-4].minor.yy528->x.pList = pList;
if( ALWAYS(pList->nExpr) ){
- yymsp[-4].minor.yy202->flags |= pList->a[0].pExpr->flags & EP_Propagate;
+ yymsp[-4].minor.yy528->flags |= pList->a[0].pExpr->flags & EP_Propagate;
}
}else{
sqlcipher_sqlite3ExprListDelete(pParse->db, pList);
}
}
break;
- case 185: /* expr ::= expr AND expr */
-{yymsp[-2].minor.yy202=sqlcipher_sqlite3ExprAnd(pParse,yymsp[-2].minor.yy202,yymsp[0].minor.yy202);}
+ case 194: /* expr ::= expr AND expr */
+{yymsp[-2].minor.yy528=sqlcipher_sqlite3ExprAnd(pParse,yymsp[-2].minor.yy528,yymsp[0].minor.yy528);}
break;
- case 186: /* expr ::= expr OR expr */
- case 187: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==187);
- case 188: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==188);
- case 189: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==189);
- case 190: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==190);
- case 191: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==191);
- case 192: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==192);
-{yymsp[-2].minor.yy202=sqlcipher_sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy202,yymsp[0].minor.yy202);}
+ case 195: /* expr ::= expr OR expr */
+ case 196: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==196);
+ case 197: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==197);
+ case 198: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==198);
+ case 199: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==199);
+ case 200: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==200);
+ case 201: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==201);
+{yymsp[-2].minor.yy528=sqlcipher_sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy528,yymsp[0].minor.yy528);}
break;
- case 193: /* likeop ::= NOT LIKE_KW|MATCH */
+ case 202: /* likeop ::= NOT LIKE_KW|MATCH */
{yymsp[-1].minor.yy0=yymsp[0].minor.yy0; yymsp[-1].minor.yy0.n|=0x80000000; /*yymsp[-1].minor.yy0-overwrite-yymsp[0].minor.yy0*/}
break;
- case 194: /* expr ::= expr likeop expr */
+ case 203: /* expr ::= expr likeop expr */
{
ExprList *pList;
int bNot = yymsp[-1].minor.yy0.n & 0x80000000;
yymsp[-1].minor.yy0.n &= 0x7fffffff;
- pList = sqlcipher_sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy202);
- pList = sqlcipher_sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy202);
- yymsp[-2].minor.yy202 = sqlcipher_sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0);
- if( bNot ) yymsp[-2].minor.yy202 = sqlcipher_sqlite3PExpr(pParse, TK_NOT, yymsp[-2].minor.yy202, 0);
- if( yymsp[-2].minor.yy202 ) yymsp[-2].minor.yy202->flags |= EP_InfixFunc;
+ pList = sqlcipher_sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy528);
+ pList = sqlcipher_sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy528);
+ yymsp[-2].minor.yy528 = sqlcipher_sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0);
+ if( bNot ) yymsp[-2].minor.yy528 = sqlcipher_sqlite3PExpr(pParse, TK_NOT, yymsp[-2].minor.yy528, 0);
+ if( yymsp[-2].minor.yy528 ) yymsp[-2].minor.yy528->flags |= EP_InfixFunc;
}
break;
- case 195: /* expr ::= expr likeop expr ESCAPE expr */
+ case 204: /* expr ::= expr likeop expr ESCAPE expr */
{
ExprList *pList;
int bNot = yymsp[-3].minor.yy0.n & 0x80000000;
yymsp[-3].minor.yy0.n &= 0x7fffffff;
- pList = sqlcipher_sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy202);
- pList = sqlcipher_sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy202);
- pList = sqlcipher_sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy202);
- yymsp[-4].minor.yy202 = sqlcipher_sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy0, 0);
- if( bNot ) yymsp[-4].minor.yy202 = sqlcipher_sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy202, 0);
- if( yymsp[-4].minor.yy202 ) yymsp[-4].minor.yy202->flags |= EP_InfixFunc;
+ pList = sqlcipher_sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy528);
+ pList = sqlcipher_sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy528);
+ pList = sqlcipher_sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy528);
+ yymsp[-4].minor.yy528 = sqlcipher_sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy0, 0);
+ if( bNot ) yymsp[-4].minor.yy528 = sqlcipher_sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy528, 0);
+ if( yymsp[-4].minor.yy528 ) yymsp[-4].minor.yy528->flags |= EP_InfixFunc;
}
break;
- case 196: /* expr ::= expr ISNULL|NOTNULL */
-{yymsp[-1].minor.yy202 = sqlcipher_sqlite3PExpr(pParse,yymsp[0].major,yymsp[-1].minor.yy202,0);}
+ case 205: /* expr ::= expr ISNULL|NOTNULL */
+{yymsp[-1].minor.yy528 = sqlcipher_sqlite3PExpr(pParse,yymsp[0].major,yymsp[-1].minor.yy528,0);}
+ break;
+ case 206: /* expr ::= expr NOT NULL */
+{yymsp[-2].minor.yy528 = sqlcipher_sqlite3PExpr(pParse,TK_NOTNULL,yymsp[-2].minor.yy528,0);}
+ break;
+ case 207: /* expr ::= expr IS expr */
+{
+ yymsp[-2].minor.yy528 = sqlcipher_sqlite3PExpr(pParse,TK_IS,yymsp[-2].minor.yy528,yymsp[0].minor.yy528);
+ binaryToUnaryIfNull(pParse, yymsp[0].minor.yy528, yymsp[-2].minor.yy528, TK_ISNULL);
+}
break;
- case 197: /* expr ::= expr NOT NULL */
-{yymsp[-2].minor.yy202 = sqlcipher_sqlite3PExpr(pParse,TK_NOTNULL,yymsp[-2].minor.yy202,0);}
+ case 208: /* expr ::= expr IS NOT expr */
+{
+ yymsp[-3].minor.yy528 = sqlcipher_sqlite3PExpr(pParse,TK_ISNOT,yymsp[-3].minor.yy528,yymsp[0].minor.yy528);
+ binaryToUnaryIfNull(pParse, yymsp[0].minor.yy528, yymsp[-3].minor.yy528, TK_NOTNULL);
+}
break;
- case 198: /* expr ::= expr IS expr */
+ case 209: /* expr ::= expr IS NOT DISTINCT FROM expr */
{
- yymsp[-2].minor.yy202 = sqlcipher_sqlite3PExpr(pParse,TK_IS,yymsp[-2].minor.yy202,yymsp[0].minor.yy202);
- binaryToUnaryIfNull(pParse, yymsp[0].minor.yy202, yymsp[-2].minor.yy202, TK_ISNULL);
+ yymsp[-5].minor.yy528 = sqlcipher_sqlite3PExpr(pParse,TK_IS,yymsp[-5].minor.yy528,yymsp[0].minor.yy528);
+ binaryToUnaryIfNull(pParse, yymsp[0].minor.yy528, yymsp[-5].minor.yy528, TK_ISNULL);
}
break;
- case 199: /* expr ::= expr IS NOT expr */
+ case 210: /* expr ::= expr IS DISTINCT FROM expr */
{
- yymsp[-3].minor.yy202 = sqlcipher_sqlite3PExpr(pParse,TK_ISNOT,yymsp[-3].minor.yy202,yymsp[0].minor.yy202);
- binaryToUnaryIfNull(pParse, yymsp[0].minor.yy202, yymsp[-3].minor.yy202, TK_NOTNULL);
+ yymsp[-4].minor.yy528 = sqlcipher_sqlite3PExpr(pParse,TK_ISNOT,yymsp[-4].minor.yy528,yymsp[0].minor.yy528);
+ binaryToUnaryIfNull(pParse, yymsp[0].minor.yy528, yymsp[-4].minor.yy528, TK_NOTNULL);
}
break;
- case 200: /* expr ::= NOT expr */
- case 201: /* expr ::= BITNOT expr */ yytestcase(yyruleno==201);
-{yymsp[-1].minor.yy202 = sqlcipher_sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy202, 0);/*A-overwrites-B*/}
+ case 211: /* expr ::= NOT expr */
+ case 212: /* expr ::= BITNOT expr */ yytestcase(yyruleno==212);
+{yymsp[-1].minor.yy528 = sqlcipher_sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy528, 0);/*A-overwrites-B*/}
break;
- case 202: /* expr ::= PLUS|MINUS expr */
+ case 213: /* expr ::= PLUS|MINUS expr */
{
- yymsp[-1].minor.yy202 = sqlcipher_sqlite3PExpr(pParse, yymsp[-1].major==TK_PLUS ? TK_UPLUS : TK_UMINUS, yymsp[0].minor.yy202, 0);
+ yymsp[-1].minor.yy528 = sqlcipher_sqlite3PExpr(pParse, yymsp[-1].major==TK_PLUS ? TK_UPLUS : TK_UMINUS, yymsp[0].minor.yy528, 0);
/*A-overwrites-B*/
}
break;
- case 203: /* between_op ::= BETWEEN */
- case 206: /* in_op ::= IN */ yytestcase(yyruleno==206);
-{yymsp[0].minor.yy192 = 0;}
+ case 214: /* expr ::= expr PTR expr */
+{
+ ExprList *pList = sqlcipher_sqlite3ExprListAppend(pParse, 0, yymsp[-2].minor.yy528);
+ pList = sqlcipher_sqlite3ExprListAppend(pParse, pList, yymsp[0].minor.yy528);
+ yylhsminor.yy528 = sqlcipher_sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0);
+}
+ yymsp[-2].minor.yy528 = yylhsminor.yy528;
break;
- case 205: /* expr ::= expr between_op expr AND expr */
+ case 215: /* between_op ::= BETWEEN */
+ case 218: /* in_op ::= IN */ yytestcase(yyruleno==218);
+{yymsp[0].minor.yy394 = 0;}
+ break;
+ case 217: /* expr ::= expr between_op expr AND expr */
{
- ExprList *pList = sqlcipher_sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy202);
- pList = sqlcipher_sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy202);
- yymsp[-4].minor.yy202 = sqlcipher_sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy202, 0);
- if( yymsp[-4].minor.yy202 ){
- yymsp[-4].minor.yy202->x.pList = pList;
+ ExprList *pList = sqlcipher_sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy528);
+ pList = sqlcipher_sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy528);
+ yymsp[-4].minor.yy528 = sqlcipher_sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy528, 0);
+ if( yymsp[-4].minor.yy528 ){
+ yymsp[-4].minor.yy528->x.pList = pList;
}else{
sqlcipher_sqlite3ExprListDelete(pParse->db, pList);
}
- if( yymsp[-3].minor.yy192 ) yymsp[-4].minor.yy202 = sqlcipher_sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy202, 0);
+ if( yymsp[-3].minor.yy394 ) yymsp[-4].minor.yy528 = sqlcipher_sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy528, 0);
}
break;
- case 208: /* expr ::= expr in_op LP exprlist RP */
+ case 220: /* expr ::= expr in_op LP exprlist RP */
{
- if( yymsp[-1].minor.yy242==0 ){
+ if( yymsp[-1].minor.yy322==0 ){
/* Expressions of the form
**
** expr1 IN ()
@@ -164129,197 +173427,206 @@ static YYACTIONTYPE yy_reduce(
** simplify to constants 0 (false) and 1 (true), respectively,
** regardless of the value of expr1.
*/
- sqlcipher_sqlite3ExprUnmapAndDelete(pParse, yymsp[-4].minor.yy202);
- yymsp[-4].minor.yy202 = sqlcipher_sqlite3Expr(pParse->db, TK_INTEGER, yymsp[-3].minor.yy192 ? "1" : "0");
- }else if( yymsp[-1].minor.yy242->nExpr==1 && sqlcipher_sqlite3ExprIsConstant(yymsp[-1].minor.yy242->a[0].pExpr) ){
- Expr *pRHS = yymsp[-1].minor.yy242->a[0].pExpr;
- yymsp[-1].minor.yy242->a[0].pExpr = 0;
- sqlcipher_sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy242);
- pRHS = sqlcipher_sqlite3PExpr(pParse, TK_UPLUS, pRHS, 0);
- yymsp[-4].minor.yy202 = sqlcipher_sqlite3PExpr(pParse, TK_EQ, yymsp[-4].minor.yy202, pRHS);
- if( yymsp[-3].minor.yy192 ) yymsp[-4].minor.yy202 = sqlcipher_sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy202, 0);
- }else{
- yymsp[-4].minor.yy202 = sqlcipher_sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy202, 0);
- if( yymsp[-4].minor.yy202 ){
- yymsp[-4].minor.yy202->x.pList = yymsp[-1].minor.yy242;
- sqlcipher_sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy202);
+ sqlcipher_sqlite3ExprUnmapAndDelete(pParse, yymsp[-4].minor.yy528);
+ yymsp[-4].minor.yy528 = sqlcipher_sqlite3Expr(pParse->db, TK_STRING, yymsp[-3].minor.yy394 ? "true" : "false");
+ if( yymsp[-4].minor.yy528 ) sqlcipher_sqlite3ExprIdToTrueFalse(yymsp[-4].minor.yy528);
+ }else{
+ Expr *pRHS = yymsp[-1].minor.yy322->a[0].pExpr;
+ if( yymsp[-1].minor.yy322->nExpr==1 && sqlcipher_sqlite3ExprIsConstant(pRHS) && yymsp[-4].minor.yy528->op!=TK_VECTOR ){
+ yymsp[-1].minor.yy322->a[0].pExpr = 0;
+ sqlcipher_sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy322);
+ pRHS = sqlcipher_sqlite3PExpr(pParse, TK_UPLUS, pRHS, 0);
+ yymsp[-4].minor.yy528 = sqlcipher_sqlite3PExpr(pParse, TK_EQ, yymsp[-4].minor.yy528, pRHS);
}else{
- sqlcipher_sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy242);
+ yymsp[-4].minor.yy528 = sqlcipher_sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy528, 0);
+ if( yymsp[-4].minor.yy528==0 ){
+ sqlcipher_sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy322);
+ }else if( yymsp[-4].minor.yy528->pLeft->op==TK_VECTOR ){
+ int nExpr = yymsp[-4].minor.yy528->pLeft->x.pList->nExpr;
+ Select *pSelectRHS = sqlcipher_sqlite3ExprListToValues(pParse, nExpr, yymsp[-1].minor.yy322);
+ if( pSelectRHS ){
+ parserDoubleLinkSelect(pParse, pSelectRHS);
+ sqlcipher_sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy528, pSelectRHS);
+ }
+ }else{
+ yymsp[-4].minor.yy528->x.pList = yymsp[-1].minor.yy322;
+ sqlcipher_sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy528);
+ }
}
- if( yymsp[-3].minor.yy192 ) yymsp[-4].minor.yy202 = sqlcipher_sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy202, 0);
+ if( yymsp[-3].minor.yy394 ) yymsp[-4].minor.yy528 = sqlcipher_sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy528, 0);
}
}
break;
- case 209: /* expr ::= LP select RP */
+ case 221: /* expr ::= LP select RP */
{
- yymsp[-2].minor.yy202 = sqlcipher_sqlite3PExpr(pParse, TK_SELECT, 0, 0);
- sqlcipher_sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy202, yymsp[-1].minor.yy539);
+ yymsp[-2].minor.yy528 = sqlcipher_sqlite3PExpr(pParse, TK_SELECT, 0, 0);
+ sqlcipher_sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy528, yymsp[-1].minor.yy47);
}
break;
- case 210: /* expr ::= expr in_op LP select RP */
+ case 222: /* expr ::= expr in_op LP select RP */
{
- yymsp[-4].minor.yy202 = sqlcipher_sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy202, 0);
- sqlcipher_sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy202, yymsp[-1].minor.yy539);
- if( yymsp[-3].minor.yy192 ) yymsp[-4].minor.yy202 = sqlcipher_sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy202, 0);
+ yymsp[-4].minor.yy528 = sqlcipher_sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy528, 0);
+ sqlcipher_sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy528, yymsp[-1].minor.yy47);
+ if( yymsp[-3].minor.yy394 ) yymsp[-4].minor.yy528 = sqlcipher_sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy528, 0);
}
break;
- case 211: /* expr ::= expr in_op nm dbnm paren_exprlist */
+ case 223: /* expr ::= expr in_op nm dbnm paren_exprlist */
{
SrcList *pSrc = sqlcipher_sqlite3SrcListAppend(pParse, 0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);
Select *pSelect = sqlcipher_sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0);
- if( yymsp[0].minor.yy242 ) sqlcipher_sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy242);
- yymsp[-4].minor.yy202 = sqlcipher_sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy202, 0);
- sqlcipher_sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy202, pSelect);
- if( yymsp[-3].minor.yy192 ) yymsp[-4].minor.yy202 = sqlcipher_sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy202, 0);
+ if( yymsp[0].minor.yy322 ) sqlcipher_sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy322);
+ yymsp[-4].minor.yy528 = sqlcipher_sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy528, 0);
+ sqlcipher_sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy528, pSelect);
+ if( yymsp[-3].minor.yy394 ) yymsp[-4].minor.yy528 = sqlcipher_sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy528, 0);
}
break;
- case 212: /* expr ::= EXISTS LP select RP */
+ case 224: /* expr ::= EXISTS LP select RP */
{
Expr *p;
- p = yymsp[-3].minor.yy202 = sqlcipher_sqlite3PExpr(pParse, TK_EXISTS, 0, 0);
- sqlcipher_sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy539);
+ p = yymsp[-3].minor.yy528 = sqlcipher_sqlite3PExpr(pParse, TK_EXISTS, 0, 0);
+ sqlcipher_sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy47);
}
break;
- case 213: /* expr ::= CASE case_operand case_exprlist case_else END */
+ case 225: /* expr ::= CASE case_operand case_exprlist case_else END */
{
- yymsp[-4].minor.yy202 = sqlcipher_sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy202, 0);
- if( yymsp[-4].minor.yy202 ){
- yymsp[-4].minor.yy202->x.pList = yymsp[-1].minor.yy202 ? sqlcipher_sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy242,yymsp[-1].minor.yy202) : yymsp[-2].minor.yy242;
- sqlcipher_sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy202);
+ yymsp[-4].minor.yy528 = sqlcipher_sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy528, 0);
+ if( yymsp[-4].minor.yy528 ){
+ yymsp[-4].minor.yy528->x.pList = yymsp[-1].minor.yy528 ? sqlcipher_sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy322,yymsp[-1].minor.yy528) : yymsp[-2].minor.yy322;
+ sqlcipher_sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy528);
}else{
- sqlcipher_sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy242);
- sqlcipher_sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy202);
+ sqlcipher_sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy322);
+ sqlcipher_sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy528);
}
}
break;
- case 214: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */
+ case 226: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */
{
- yymsp[-4].minor.yy242 = sqlcipher_sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy242, yymsp[-2].minor.yy202);
- yymsp[-4].minor.yy242 = sqlcipher_sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy242, yymsp[0].minor.yy202);
+ yymsp[-4].minor.yy322 = sqlcipher_sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy322, yymsp[-2].minor.yy528);
+ yymsp[-4].minor.yy322 = sqlcipher_sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy322, yymsp[0].minor.yy528);
}
break;
- case 215: /* case_exprlist ::= WHEN expr THEN expr */
+ case 227: /* case_exprlist ::= WHEN expr THEN expr */
{
- yymsp[-3].minor.yy242 = sqlcipher_sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy202);
- yymsp[-3].minor.yy242 = sqlcipher_sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy242, yymsp[0].minor.yy202);
+ yymsp[-3].minor.yy322 = sqlcipher_sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy528);
+ yymsp[-3].minor.yy322 = sqlcipher_sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy322, yymsp[0].minor.yy528);
}
break;
- case 218: /* case_operand ::= expr */
-{yymsp[0].minor.yy202 = yymsp[0].minor.yy202; /*A-overwrites-X*/}
+ case 230: /* case_operand ::= expr */
+{yymsp[0].minor.yy528 = yymsp[0].minor.yy528; /*A-overwrites-X*/}
break;
- case 221: /* nexprlist ::= nexprlist COMMA expr */
-{yymsp[-2].minor.yy242 = sqlcipher_sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy242,yymsp[0].minor.yy202);}
+ case 233: /* nexprlist ::= nexprlist COMMA expr */
+{yymsp[-2].minor.yy322 = sqlcipher_sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy322,yymsp[0].minor.yy528);}
break;
- case 222: /* nexprlist ::= expr */
-{yymsp[0].minor.yy242 = sqlcipher_sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy202); /*A-overwrites-Y*/}
+ case 234: /* nexprlist ::= expr */
+{yymsp[0].minor.yy322 = sqlcipher_sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy528); /*A-overwrites-Y*/}
break;
- case 224: /* paren_exprlist ::= LP exprlist RP */
- case 229: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==229);
-{yymsp[-2].minor.yy242 = yymsp[-1].minor.yy242;}
+ case 236: /* paren_exprlist ::= LP exprlist RP */
+ case 241: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==241);
+{yymsp[-2].minor.yy322 = yymsp[-1].minor.yy322;}
break;
- case 225: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
+ case 237: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
{
sqlcipher_sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0,
- sqlcipher_sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy242, yymsp[-10].minor.yy192,
- &yymsp[-11].minor.yy0, yymsp[0].minor.yy202, SQLITE_SO_ASC, yymsp[-8].minor.yy192, SQLITE_IDXTYPE_APPDEF);
+ sqlcipher_sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy322, yymsp[-10].minor.yy394,
+ &yymsp[-11].minor.yy0, yymsp[0].minor.yy528, SQLITE_SO_ASC, yymsp[-8].minor.yy394, SQLITE_IDXTYPE_APPDEF);
if( IN_RENAME_OBJECT && pParse->pNewIndex ){
sqlcipher_sqlite3RenameTokenMap(pParse, pParse->pNewIndex->zName, &yymsp[-4].minor.yy0);
}
}
break;
- case 226: /* uniqueflag ::= UNIQUE */
- case 268: /* raisetype ::= ABORT */ yytestcase(yyruleno==268);
-{yymsp[0].minor.yy192 = OE_Abort;}
+ case 238: /* uniqueflag ::= UNIQUE */
+ case 280: /* raisetype ::= ABORT */ yytestcase(yyruleno==280);
+{yymsp[0].minor.yy394 = OE_Abort;}
break;
- case 227: /* uniqueflag ::= */
-{yymsp[1].minor.yy192 = OE_None;}
+ case 239: /* uniqueflag ::= */
+{yymsp[1].minor.yy394 = OE_None;}
break;
- case 230: /* eidlist ::= eidlist COMMA nm collate sortorder */
+ case 242: /* eidlist ::= eidlist COMMA nm collate sortorder */
{
- yymsp[-4].minor.yy242 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy242, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy192, yymsp[0].minor.yy192);
+ yymsp[-4].minor.yy322 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy322, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy394, yymsp[0].minor.yy394);
}
break;
- case 231: /* eidlist ::= nm collate sortorder */
+ case 243: /* eidlist ::= nm collate sortorder */
{
- yymsp[-2].minor.yy242 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy192, yymsp[0].minor.yy192); /*A-overwrites-Y*/
+ yymsp[-2].minor.yy322 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy394, yymsp[0].minor.yy394); /*A-overwrites-Y*/
}
break;
- case 234: /* cmd ::= DROP INDEX ifexists fullname */
-{sqlcipher_sqlite3DropIndex(pParse, yymsp[0].minor.yy47, yymsp[-1].minor.yy192);}
+ case 246: /* cmd ::= DROP INDEX ifexists fullname */
+{sqlcipher_sqlite3DropIndex(pParse, yymsp[0].minor.yy131, yymsp[-1].minor.yy394);}
break;
- case 235: /* cmd ::= VACUUM vinto */
-{sqlcipher_sqlite3Vacuum(pParse,0,yymsp[0].minor.yy202);}
+ case 247: /* cmd ::= VACUUM vinto */
+{sqlcipher_sqlite3Vacuum(pParse,0,yymsp[0].minor.yy528);}
break;
- case 236: /* cmd ::= VACUUM nm vinto */
-{sqlcipher_sqlite3Vacuum(pParse,&yymsp[-1].minor.yy0,yymsp[0].minor.yy202);}
+ case 248: /* cmd ::= VACUUM nm vinto */
+{sqlcipher_sqlite3Vacuum(pParse,&yymsp[-1].minor.yy0,yymsp[0].minor.yy528);}
break;
- case 239: /* cmd ::= PRAGMA nm dbnm */
+ case 251: /* cmd ::= PRAGMA nm dbnm */
{sqlcipher_sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);}
break;
- case 240: /* cmd ::= PRAGMA nm dbnm EQ nmnum */
+ case 252: /* cmd ::= PRAGMA nm dbnm EQ nmnum */
{sqlcipher_sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);}
break;
- case 241: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */
+ case 253: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */
{sqlcipher_sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);}
break;
- case 242: /* cmd ::= PRAGMA nm dbnm EQ minus_num */
+ case 254: /* cmd ::= PRAGMA nm dbnm EQ minus_num */
{sqlcipher_sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);}
break;
- case 243: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */
+ case 255: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */
{sqlcipher_sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,1);}
break;
- case 246: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
+ case 258: /* 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;
- sqlcipher_sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy447, &all);
+ sqlcipher_sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy33, &all);
}
break;
- case 247: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
+ case 259: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
{
- sqlcipher_sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy192, yymsp[-4].minor.yy230.a, yymsp[-4].minor.yy230.b, yymsp[-2].minor.yy47, yymsp[0].minor.yy202, yymsp[-10].minor.yy192, yymsp[-8].minor.yy192);
+ sqlcipher_sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy394, yymsp[-4].minor.yy180.a, yymsp[-4].minor.yy180.b, yymsp[-2].minor.yy131, yymsp[0].minor.yy528, yymsp[-10].minor.yy394, yymsp[-8].minor.yy394);
yymsp[-10].minor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0); /*A-overwrites-T*/
}
break;
- case 248: /* trigger_time ::= BEFORE|AFTER */
-{ yymsp[0].minor.yy192 = yymsp[0].major; /*A-overwrites-X*/ }
+ case 260: /* trigger_time ::= BEFORE|AFTER */
+{ yymsp[0].minor.yy394 = yymsp[0].major; /*A-overwrites-X*/ }
break;
- case 249: /* trigger_time ::= INSTEAD OF */
-{ yymsp[-1].minor.yy192 = TK_INSTEAD;}
+ case 261: /* trigger_time ::= INSTEAD OF */
+{ yymsp[-1].minor.yy394 = TK_INSTEAD;}
break;
- case 250: /* trigger_time ::= */
-{ yymsp[1].minor.yy192 = TK_BEFORE; }
+ case 262: /* trigger_time ::= */
+{ yymsp[1].minor.yy394 = TK_BEFORE; }
break;
- case 251: /* trigger_event ::= DELETE|INSERT */
- case 252: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==252);
-{yymsp[0].minor.yy230.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy230.b = 0;}
+ case 263: /* trigger_event ::= DELETE|INSERT */
+ case 264: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==264);
+{yymsp[0].minor.yy180.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy180.b = 0;}
break;
- case 253: /* trigger_event ::= UPDATE OF idlist */
-{yymsp[-2].minor.yy230.a = TK_UPDATE; yymsp[-2].minor.yy230.b = yymsp[0].minor.yy600;}
+ case 265: /* trigger_event ::= UPDATE OF idlist */
+{yymsp[-2].minor.yy180.a = TK_UPDATE; yymsp[-2].minor.yy180.b = yymsp[0].minor.yy254;}
break;
- case 254: /* when_clause ::= */
- case 273: /* key_opt ::= */ yytestcase(yyruleno==273);
-{ yymsp[1].minor.yy202 = 0; }
+ case 266: /* when_clause ::= */
+ case 285: /* key_opt ::= */ yytestcase(yyruleno==285);
+{ yymsp[1].minor.yy528 = 0; }
break;
- case 255: /* when_clause ::= WHEN expr */
- case 274: /* key_opt ::= KEY expr */ yytestcase(yyruleno==274);
-{ yymsp[-1].minor.yy202 = yymsp[0].minor.yy202; }
+ case 267: /* when_clause ::= WHEN expr */
+ case 286: /* key_opt ::= KEY expr */ yytestcase(yyruleno==286);
+{ yymsp[-1].minor.yy528 = yymsp[0].minor.yy528; }
break;
- case 256: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
+ case 268: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
{
- assert( yymsp[-2].minor.yy447!=0 );
- yymsp[-2].minor.yy447->pLast->pNext = yymsp[-1].minor.yy447;
- yymsp[-2].minor.yy447->pLast = yymsp[-1].minor.yy447;
+ assert( yymsp[-2].minor.yy33!=0 );
+ yymsp[-2].minor.yy33->pLast->pNext = yymsp[-1].minor.yy33;
+ yymsp[-2].minor.yy33->pLast = yymsp[-1].minor.yy33;
}
break;
- case 257: /* trigger_cmd_list ::= trigger_cmd SEMI */
+ case 269: /* trigger_cmd_list ::= trigger_cmd SEMI */
{
- assert( yymsp[-1].minor.yy447!=0 );
- yymsp[-1].minor.yy447->pLast = yymsp[-1].minor.yy447;
+ assert( yymsp[-1].minor.yy33!=0 );
+ yymsp[-1].minor.yy33->pLast = yymsp[-1].minor.yy33;
}
break;
- case 258: /* trnm ::= nm DOT nm */
+ case 270: /* trnm ::= nm DOT nm */
{
yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;
sqlcipher_sqlite3ErrorMsg(pParse,
@@ -164327,344 +173634,370 @@ static YYACTIONTYPE yy_reduce(
"statements within triggers");
}
break;
- case 259: /* tridxby ::= INDEXED BY nm */
+ case 271: /* tridxby ::= INDEXED BY nm */
{
sqlcipher_sqlite3ErrorMsg(pParse,
"the INDEXED BY clause is not allowed on UPDATE or DELETE statements "
"within triggers");
}
break;
- case 260: /* tridxby ::= NOT INDEXED */
+ case 272: /* tridxby ::= NOT INDEXED */
{
sqlcipher_sqlite3ErrorMsg(pParse,
"the NOT INDEXED clause is not allowed on UPDATE or DELETE statements "
"within triggers");
}
break;
- case 261: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */
-{yylhsminor.yy447 = sqlcipher_sqlite3TriggerUpdateStep(pParse, &yymsp[-6].minor.yy0, yymsp[-2].minor.yy47, yymsp[-3].minor.yy242, yymsp[-1].minor.yy202, yymsp[-7].minor.yy192, yymsp[-8].minor.yy0.z, yymsp[0].minor.yy436);}
- yymsp[-8].minor.yy447 = yylhsminor.yy447;
+ case 273: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist from where_opt scanpt */
+{yylhsminor.yy33 = sqlcipher_sqlite3TriggerUpdateStep(pParse, &yymsp[-6].minor.yy0, yymsp[-2].minor.yy131, yymsp[-3].minor.yy322, yymsp[-1].minor.yy528, yymsp[-7].minor.yy394, yymsp[-8].minor.yy0.z, yymsp[0].minor.yy522);}
+ yymsp[-8].minor.yy33 = yylhsminor.yy33;
break;
- case 262: /* trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
+ case 274: /* trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
{
- yylhsminor.yy447 = sqlcipher_sqlite3TriggerInsertStep(pParse,&yymsp[-4].minor.yy0,yymsp[-3].minor.yy600,yymsp[-2].minor.yy539,yymsp[-6].minor.yy192,yymsp[-1].minor.yy318,yymsp[-7].minor.yy436,yymsp[0].minor.yy436);/*yylhsminor.yy447-overwrites-yymsp[-6].minor.yy192*/
+ yylhsminor.yy33 = sqlcipher_sqlite3TriggerInsertStep(pParse,&yymsp[-4].minor.yy0,yymsp[-3].minor.yy254,yymsp[-2].minor.yy47,yymsp[-6].minor.yy394,yymsp[-1].minor.yy444,yymsp[-7].minor.yy522,yymsp[0].minor.yy522);/*yylhsminor.yy33-overwrites-yymsp[-6].minor.yy394*/
}
- yymsp[-7].minor.yy447 = yylhsminor.yy447;
+ yymsp[-7].minor.yy33 = yylhsminor.yy33;
break;
- case 263: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
-{yylhsminor.yy447 = sqlcipher_sqlite3TriggerDeleteStep(pParse, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy202, yymsp[-5].minor.yy0.z, yymsp[0].minor.yy436);}
- yymsp[-5].minor.yy447 = yylhsminor.yy447;
+ case 275: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
+{yylhsminor.yy33 = sqlcipher_sqlite3TriggerDeleteStep(pParse, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy528, yymsp[-5].minor.yy0.z, yymsp[0].minor.yy522);}
+ yymsp[-5].minor.yy33 = yylhsminor.yy33;
break;
- case 264: /* trigger_cmd ::= scanpt select scanpt */
-{yylhsminor.yy447 = sqlcipher_sqlite3TriggerSelectStep(pParse->db, yymsp[-1].minor.yy539, yymsp[-2].minor.yy436, yymsp[0].minor.yy436); /*yylhsminor.yy447-overwrites-yymsp[-1].minor.yy539*/}
- yymsp[-2].minor.yy447 = yylhsminor.yy447;
+ case 276: /* trigger_cmd ::= scanpt select scanpt */
+{yylhsminor.yy33 = sqlcipher_sqlite3TriggerSelectStep(pParse->db, yymsp[-1].minor.yy47, yymsp[-2].minor.yy522, yymsp[0].minor.yy522); /*yylhsminor.yy33-overwrites-yymsp[-1].minor.yy47*/}
+ yymsp[-2].minor.yy33 = yylhsminor.yy33;
break;
- case 265: /* expr ::= RAISE LP IGNORE RP */
+ case 277: /* expr ::= RAISE LP IGNORE RP */
{
- yymsp[-3].minor.yy202 = sqlcipher_sqlite3PExpr(pParse, TK_RAISE, 0, 0);
- if( yymsp[-3].minor.yy202 ){
- yymsp[-3].minor.yy202->affExpr = OE_Ignore;
+ yymsp[-3].minor.yy528 = sqlcipher_sqlite3PExpr(pParse, TK_RAISE, 0, 0);
+ if( yymsp[-3].minor.yy528 ){
+ yymsp[-3].minor.yy528->affExpr = OE_Ignore;
}
}
break;
- case 266: /* expr ::= RAISE LP raisetype COMMA nm RP */
+ case 278: /* expr ::= RAISE LP raisetype COMMA nm RP */
{
- yymsp[-5].minor.yy202 = sqlcipher_sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1);
- if( yymsp[-5].minor.yy202 ) {
- yymsp[-5].minor.yy202->affExpr = (char)yymsp[-3].minor.yy192;
+ yymsp[-5].minor.yy528 = sqlcipher_sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1);
+ if( yymsp[-5].minor.yy528 ) {
+ yymsp[-5].minor.yy528->affExpr = (char)yymsp[-3].minor.yy394;
}
}
break;
- case 267: /* raisetype ::= ROLLBACK */
-{yymsp[0].minor.yy192 = OE_Rollback;}
+ case 279: /* raisetype ::= ROLLBACK */
+{yymsp[0].minor.yy394 = OE_Rollback;}
break;
- case 269: /* raisetype ::= FAIL */
-{yymsp[0].minor.yy192 = OE_Fail;}
+ case 281: /* raisetype ::= FAIL */
+{yymsp[0].minor.yy394 = OE_Fail;}
break;
- case 270: /* cmd ::= DROP TRIGGER ifexists fullname */
+ case 282: /* cmd ::= DROP TRIGGER ifexists fullname */
{
- sqlcipher_sqlite3DropTrigger(pParse,yymsp[0].minor.yy47,yymsp[-1].minor.yy192);
+ sqlcipher_sqlite3DropTrigger(pParse,yymsp[0].minor.yy131,yymsp[-1].minor.yy394);
}
break;
- case 271: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
+ case 283: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
{
- sqlcipher_sqlite3Attach(pParse, yymsp[-3].minor.yy202, yymsp[-1].minor.yy202, yymsp[0].minor.yy202);
+ sqlcipher_sqlite3Attach(pParse, yymsp[-3].minor.yy528, yymsp[-1].minor.yy528, yymsp[0].minor.yy528);
}
break;
- case 272: /* cmd ::= DETACH database_kw_opt expr */
+ case 284: /* cmd ::= DETACH database_kw_opt expr */
{
- sqlcipher_sqlite3Detach(pParse, yymsp[0].minor.yy202);
+ sqlcipher_sqlite3Detach(pParse, yymsp[0].minor.yy528);
}
break;
- case 275: /* cmd ::= REINDEX */
+ case 287: /* cmd ::= REINDEX */
{sqlcipher_sqlite3Reindex(pParse, 0, 0);}
break;
- case 276: /* cmd ::= REINDEX nm dbnm */
+ case 288: /* cmd ::= REINDEX nm dbnm */
{sqlcipher_sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
break;
- case 277: /* cmd ::= ANALYZE */
+ case 289: /* cmd ::= ANALYZE */
{sqlcipher_sqlite3Analyze(pParse, 0, 0);}
break;
- case 278: /* cmd ::= ANALYZE nm dbnm */
+ case 290: /* cmd ::= ANALYZE nm dbnm */
{sqlcipher_sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
break;
- case 279: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
+ case 291: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
{
- sqlcipher_sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy47,&yymsp[0].minor.yy0);
+ sqlcipher_sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy131,&yymsp[0].minor.yy0);
}
break;
- case 280: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
+ case 292: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
{
yymsp[-1].minor.yy0.n = (int)(pParse->sLastToken.z-yymsp[-1].minor.yy0.z) + pParse->sLastToken.n;
sqlcipher_sqlite3AlterFinishAddColumn(pParse, &yymsp[-1].minor.yy0);
}
break;
- case 281: /* add_column_fullname ::= fullname */
+ case 293: /* cmd ::= ALTER TABLE fullname DROP kwcolumn_opt nm */
+{
+ sqlcipher_sqlite3AlterDropColumn(pParse, yymsp[-3].minor.yy131, &yymsp[0].minor.yy0);
+}
+ break;
+ case 294: /* add_column_fullname ::= fullname */
{
disableLookaside(pParse);
- sqlcipher_sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy47);
+ sqlcipher_sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy131);
}
break;
- case 282: /* cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
+ case 295: /* cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
{
- sqlcipher_sqlite3AlterRenameColumn(pParse, yymsp[-5].minor.yy47, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0);
+ sqlcipher_sqlite3AlterRenameColumn(pParse, yymsp[-5].minor.yy131, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0);
}
break;
- case 283: /* cmd ::= create_vtab */
+ case 296: /* cmd ::= create_vtab */
{sqlcipher_sqlite3VtabFinishParse(pParse,0);}
break;
- case 284: /* cmd ::= create_vtab LP vtabarglist RP */
+ case 297: /* cmd ::= create_vtab LP vtabarglist RP */
{sqlcipher_sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);}
break;
- case 285: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
+ case 298: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
{
- sqlcipher_sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy192);
+ sqlcipher_sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy394);
}
break;
- case 286: /* vtabarg ::= */
+ case 299: /* vtabarg ::= */
{sqlcipher_sqlite3VtabArgInit(pParse);}
break;
- case 287: /* vtabargtoken ::= ANY */
- case 288: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==288);
- case 289: /* lp ::= LP */ yytestcase(yyruleno==289);
+ case 300: /* vtabargtoken ::= ANY */
+ case 301: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==301);
+ case 302: /* lp ::= LP */ yytestcase(yyruleno==302);
{sqlcipher_sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);}
break;
- case 290: /* with ::= WITH wqlist */
- case 291: /* with ::= WITH RECURSIVE wqlist */ yytestcase(yyruleno==291);
-{ sqlcipher_sqlite3WithPush(pParse, yymsp[0].minor.yy131, 1); }
+ case 303: /* with ::= WITH wqlist */
+ case 304: /* with ::= WITH RECURSIVE wqlist */ yytestcase(yyruleno==304);
+{ sqlcipher_sqlite3WithPush(pParse, yymsp[0].minor.yy521, 1); }
+ break;
+ case 305: /* wqas ::= AS */
+{yymsp[0].minor.yy516 = M10d_Any;}
+ break;
+ case 306: /* wqas ::= AS MATERIALIZED */
+{yymsp[-1].minor.yy516 = M10d_Yes;}
+ break;
+ case 307: /* wqas ::= AS NOT MATERIALIZED */
+{yymsp[-2].minor.yy516 = M10d_No;}
+ break;
+ case 308: /* wqitem ::= nm eidlist_opt wqas LP select RP */
+{
+ yymsp[-5].minor.yy385 = sqlcipher_sqlite3CteNew(pParse, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy322, yymsp[-1].minor.yy47, yymsp[-3].minor.yy516); /*A-overwrites-X*/
+}
break;
- case 292: /* wqlist ::= nm eidlist_opt AS LP select RP */
+ case 309: /* wqlist ::= wqitem */
{
- yymsp[-5].minor.yy131 = sqlcipher_sqlite3WithAdd(pParse, 0, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy242, yymsp[-1].minor.yy539); /*A-overwrites-X*/
+ yymsp[0].minor.yy521 = sqlcipher_sqlite3WithAdd(pParse, 0, yymsp[0].minor.yy385); /*A-overwrites-X*/
}
break;
- case 293: /* wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */
+ case 310: /* wqlist ::= wqlist COMMA wqitem */
{
- yymsp[-7].minor.yy131 = sqlcipher_sqlite3WithAdd(pParse, yymsp[-7].minor.yy131, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy242, yymsp[-1].minor.yy539);
+ yymsp[-2].minor.yy521 = sqlcipher_sqlite3WithAdd(pParse, yymsp[-2].minor.yy521, yymsp[0].minor.yy385);
}
break;
- case 294: /* windowdefn_list ::= windowdefn */
-{ yylhsminor.yy303 = yymsp[0].minor.yy303; }
- yymsp[0].minor.yy303 = yylhsminor.yy303;
+ case 311: /* windowdefn_list ::= windowdefn */
+{ yylhsminor.yy41 = yymsp[0].minor.yy41; }
+ yymsp[0].minor.yy41 = yylhsminor.yy41;
break;
- case 295: /* windowdefn_list ::= windowdefn_list COMMA windowdefn */
+ case 312: /* windowdefn_list ::= windowdefn_list COMMA windowdefn */
{
- assert( yymsp[0].minor.yy303!=0 );
- sqlcipher_sqlite3WindowChain(pParse, yymsp[0].minor.yy303, yymsp[-2].minor.yy303);
- yymsp[0].minor.yy303->pNextWin = yymsp[-2].minor.yy303;
- yylhsminor.yy303 = yymsp[0].minor.yy303;
+ assert( yymsp[0].minor.yy41!=0 );
+ sqlcipher_sqlite3WindowChain(pParse, yymsp[0].minor.yy41, yymsp[-2].minor.yy41);
+ yymsp[0].minor.yy41->pNextWin = yymsp[-2].minor.yy41;
+ yylhsminor.yy41 = yymsp[0].minor.yy41;
}
- yymsp[-2].minor.yy303 = yylhsminor.yy303;
+ yymsp[-2].minor.yy41 = yylhsminor.yy41;
break;
- case 296: /* windowdefn ::= nm AS LP window RP */
+ case 313: /* windowdefn ::= nm AS LP window RP */
{
- if( ALWAYS(yymsp[-1].minor.yy303) ){
- yymsp[-1].minor.yy303->zName = sqlcipher_sqlite3DbStrNDup(pParse->db, yymsp[-4].minor.yy0.z, yymsp[-4].minor.yy0.n);
+ if( ALWAYS(yymsp[-1].minor.yy41) ){
+ yymsp[-1].minor.yy41->zName = sqlcipher_sqlite3DbStrNDup(pParse->db, yymsp[-4].minor.yy0.z, yymsp[-4].minor.yy0.n);
}
- yylhsminor.yy303 = yymsp[-1].minor.yy303;
+ yylhsminor.yy41 = yymsp[-1].minor.yy41;
}
- yymsp[-4].minor.yy303 = yylhsminor.yy303;
+ yymsp[-4].minor.yy41 = yylhsminor.yy41;
break;
- case 297: /* window ::= PARTITION BY nexprlist orderby_opt frame_opt */
+ case 314: /* window ::= PARTITION BY nexprlist orderby_opt frame_opt */
{
- yymsp[-4].minor.yy303 = sqlcipher_sqlite3WindowAssemble(pParse, yymsp[0].minor.yy303, yymsp[-2].minor.yy242, yymsp[-1].minor.yy242, 0);
+ yymsp[-4].minor.yy41 = sqlcipher_sqlite3WindowAssemble(pParse, yymsp[0].minor.yy41, yymsp[-2].minor.yy322, yymsp[-1].minor.yy322, 0);
}
break;
- case 298: /* window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */
+ case 315: /* window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */
{
- yylhsminor.yy303 = sqlcipher_sqlite3WindowAssemble(pParse, yymsp[0].minor.yy303, yymsp[-2].minor.yy242, yymsp[-1].minor.yy242, &yymsp[-5].minor.yy0);
+ yylhsminor.yy41 = sqlcipher_sqlite3WindowAssemble(pParse, yymsp[0].minor.yy41, yymsp[-2].minor.yy322, yymsp[-1].minor.yy322, &yymsp[-5].minor.yy0);
}
- yymsp[-5].minor.yy303 = yylhsminor.yy303;
+ yymsp[-5].minor.yy41 = yylhsminor.yy41;
break;
- case 299: /* window ::= ORDER BY sortlist frame_opt */
+ case 316: /* window ::= ORDER BY sortlist frame_opt */
{
- yymsp[-3].minor.yy303 = sqlcipher_sqlite3WindowAssemble(pParse, yymsp[0].minor.yy303, 0, yymsp[-1].minor.yy242, 0);
+ yymsp[-3].minor.yy41 = sqlcipher_sqlite3WindowAssemble(pParse, yymsp[0].minor.yy41, 0, yymsp[-1].minor.yy322, 0);
}
break;
- case 300: /* window ::= nm ORDER BY sortlist frame_opt */
+ case 317: /* window ::= nm ORDER BY sortlist frame_opt */
{
- yylhsminor.yy303 = sqlcipher_sqlite3WindowAssemble(pParse, yymsp[0].minor.yy303, 0, yymsp[-1].minor.yy242, &yymsp[-4].minor.yy0);
+ yylhsminor.yy41 = sqlcipher_sqlite3WindowAssemble(pParse, yymsp[0].minor.yy41, 0, yymsp[-1].minor.yy322, &yymsp[-4].minor.yy0);
}
- yymsp[-4].minor.yy303 = yylhsminor.yy303;
+ yymsp[-4].minor.yy41 = yylhsminor.yy41;
break;
- case 301: /* window ::= frame_opt */
- case 320: /* filter_over ::= over_clause */ yytestcase(yyruleno==320);
+ case 318: /* window ::= frame_opt */
+ case 337: /* filter_over ::= over_clause */ yytestcase(yyruleno==337);
{
- yylhsminor.yy303 = yymsp[0].minor.yy303;
+ yylhsminor.yy41 = yymsp[0].minor.yy41;
}
- yymsp[0].minor.yy303 = yylhsminor.yy303;
+ yymsp[0].minor.yy41 = yylhsminor.yy41;
break;
- case 302: /* window ::= nm frame_opt */
+ case 319: /* window ::= nm frame_opt */
{
- yylhsminor.yy303 = sqlcipher_sqlite3WindowAssemble(pParse, yymsp[0].minor.yy303, 0, 0, &yymsp[-1].minor.yy0);
+ yylhsminor.yy41 = sqlcipher_sqlite3WindowAssemble(pParse, yymsp[0].minor.yy41, 0, 0, &yymsp[-1].minor.yy0);
}
- yymsp[-1].minor.yy303 = yylhsminor.yy303;
+ yymsp[-1].minor.yy41 = yylhsminor.yy41;
break;
- case 303: /* frame_opt ::= */
+ case 320: /* frame_opt ::= */
{
- yymsp[1].minor.yy303 = sqlcipher_sqlite3WindowAlloc(pParse, 0, TK_UNBOUNDED, 0, TK_CURRENT, 0, 0);
+ yymsp[1].minor.yy41 = sqlcipher_sqlite3WindowAlloc(pParse, 0, TK_UNBOUNDED, 0, TK_CURRENT, 0, 0);
}
break;
- case 304: /* frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */
+ case 321: /* frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */
{
- yylhsminor.yy303 = sqlcipher_sqlite3WindowAlloc(pParse, yymsp[-2].minor.yy192, yymsp[-1].minor.yy77.eType, yymsp[-1].minor.yy77.pExpr, TK_CURRENT, 0, yymsp[0].minor.yy58);
+ yylhsminor.yy41 = sqlcipher_sqlite3WindowAlloc(pParse, yymsp[-2].minor.yy394, yymsp[-1].minor.yy595.eType, yymsp[-1].minor.yy595.pExpr, TK_CURRENT, 0, yymsp[0].minor.yy516);
}
- yymsp[-2].minor.yy303 = yylhsminor.yy303;
+ yymsp[-2].minor.yy41 = yylhsminor.yy41;
break;
- case 305: /* frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */
+ case 322: /* frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */
{
- yylhsminor.yy303 = sqlcipher_sqlite3WindowAlloc(pParse, yymsp[-5].minor.yy192, yymsp[-3].minor.yy77.eType, yymsp[-3].minor.yy77.pExpr, yymsp[-1].minor.yy77.eType, yymsp[-1].minor.yy77.pExpr, yymsp[0].minor.yy58);
+ yylhsminor.yy41 = sqlcipher_sqlite3WindowAlloc(pParse, yymsp[-5].minor.yy394, yymsp[-3].minor.yy595.eType, yymsp[-3].minor.yy595.pExpr, yymsp[-1].minor.yy595.eType, yymsp[-1].minor.yy595.pExpr, yymsp[0].minor.yy516);
}
- yymsp[-5].minor.yy303 = yylhsminor.yy303;
+ yymsp[-5].minor.yy41 = yylhsminor.yy41;
break;
- case 307: /* frame_bound_s ::= frame_bound */
- case 309: /* frame_bound_e ::= frame_bound */ yytestcase(yyruleno==309);
-{yylhsminor.yy77 = yymsp[0].minor.yy77;}
- yymsp[0].minor.yy77 = yylhsminor.yy77;
+ case 324: /* frame_bound_s ::= frame_bound */
+ case 326: /* frame_bound_e ::= frame_bound */ yytestcase(yyruleno==326);
+{yylhsminor.yy595 = yymsp[0].minor.yy595;}
+ yymsp[0].minor.yy595 = yylhsminor.yy595;
break;
- case 308: /* frame_bound_s ::= UNBOUNDED PRECEDING */
- case 310: /* frame_bound_e ::= UNBOUNDED FOLLOWING */ yytestcase(yyruleno==310);
- case 312: /* frame_bound ::= CURRENT ROW */ yytestcase(yyruleno==312);
-{yylhsminor.yy77.eType = yymsp[-1].major; yylhsminor.yy77.pExpr = 0;}
- yymsp[-1].minor.yy77 = yylhsminor.yy77;
+ case 325: /* frame_bound_s ::= UNBOUNDED PRECEDING */
+ case 327: /* frame_bound_e ::= UNBOUNDED FOLLOWING */ yytestcase(yyruleno==327);
+ case 329: /* frame_bound ::= CURRENT ROW */ yytestcase(yyruleno==329);
+{yylhsminor.yy595.eType = yymsp[-1].major; yylhsminor.yy595.pExpr = 0;}
+ yymsp[-1].minor.yy595 = yylhsminor.yy595;
break;
- case 311: /* frame_bound ::= expr PRECEDING|FOLLOWING */
-{yylhsminor.yy77.eType = yymsp[0].major; yylhsminor.yy77.pExpr = yymsp[-1].minor.yy202;}
- yymsp[-1].minor.yy77 = yylhsminor.yy77;
+ case 328: /* frame_bound ::= expr PRECEDING|FOLLOWING */
+{yylhsminor.yy595.eType = yymsp[0].major; yylhsminor.yy595.pExpr = yymsp[-1].minor.yy528;}
+ yymsp[-1].minor.yy595 = yylhsminor.yy595;
break;
- case 313: /* frame_exclude_opt ::= */
-{yymsp[1].minor.yy58 = 0;}
+ case 330: /* frame_exclude_opt ::= */
+{yymsp[1].minor.yy516 = 0;}
break;
- case 314: /* frame_exclude_opt ::= EXCLUDE frame_exclude */
-{yymsp[-1].minor.yy58 = yymsp[0].minor.yy58;}
+ case 331: /* frame_exclude_opt ::= EXCLUDE frame_exclude */
+{yymsp[-1].minor.yy516 = yymsp[0].minor.yy516;}
break;
- case 315: /* frame_exclude ::= NO OTHERS */
- case 316: /* frame_exclude ::= CURRENT ROW */ yytestcase(yyruleno==316);
-{yymsp[-1].minor.yy58 = yymsp[-1].major; /*A-overwrites-X*/}
+ case 332: /* frame_exclude ::= NO OTHERS */
+ case 333: /* frame_exclude ::= CURRENT ROW */ yytestcase(yyruleno==333);
+{yymsp[-1].minor.yy516 = yymsp[-1].major; /*A-overwrites-X*/}
break;
- case 317: /* frame_exclude ::= GROUP|TIES */
-{yymsp[0].minor.yy58 = yymsp[0].major; /*A-overwrites-X*/}
+ case 334: /* frame_exclude ::= GROUP|TIES */
+{yymsp[0].minor.yy516 = yymsp[0].major; /*A-overwrites-X*/}
break;
- case 318: /* window_clause ::= WINDOW windowdefn_list */
-{ yymsp[-1].minor.yy303 = yymsp[0].minor.yy303; }
+ case 335: /* window_clause ::= WINDOW windowdefn_list */
+{ yymsp[-1].minor.yy41 = yymsp[0].minor.yy41; }
break;
- case 319: /* filter_over ::= filter_clause over_clause */
+ case 336: /* filter_over ::= filter_clause over_clause */
{
- yymsp[0].minor.yy303->pFilter = yymsp[-1].minor.yy202;
- yylhsminor.yy303 = yymsp[0].minor.yy303;
+ if( yymsp[0].minor.yy41 ){
+ yymsp[0].minor.yy41->pFilter = yymsp[-1].minor.yy528;
+ }else{
+ sqlcipher_sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy528);
+ }
+ yylhsminor.yy41 = yymsp[0].minor.yy41;
}
- yymsp[-1].minor.yy303 = yylhsminor.yy303;
+ yymsp[-1].minor.yy41 = yylhsminor.yy41;
break;
- case 321: /* filter_over ::= filter_clause */
+ case 338: /* filter_over ::= filter_clause */
{
- yylhsminor.yy303 = (Window*)sqlcipher_sqlite3DbMallocZero(pParse->db, sizeof(Window));
- if( yylhsminor.yy303 ){
- yylhsminor.yy303->eFrmType = TK_FILTER;
- yylhsminor.yy303->pFilter = yymsp[0].minor.yy202;
+ yylhsminor.yy41 = (Window*)sqlcipher_sqlite3DbMallocZero(pParse->db, sizeof(Window));
+ if( yylhsminor.yy41 ){
+ yylhsminor.yy41->eFrmType = TK_FILTER;
+ yylhsminor.yy41->pFilter = yymsp[0].minor.yy528;
}else{
- sqlcipher_sqlite3ExprDelete(pParse->db, yymsp[0].minor.yy202);
+ sqlcipher_sqlite3ExprDelete(pParse->db, yymsp[0].minor.yy528);
}
}
- yymsp[0].minor.yy303 = yylhsminor.yy303;
+ yymsp[0].minor.yy41 = yylhsminor.yy41;
break;
- case 322: /* over_clause ::= OVER LP window RP */
+ case 339: /* over_clause ::= OVER LP window RP */
{
- yymsp[-3].minor.yy303 = yymsp[-1].minor.yy303;
- assert( yymsp[-3].minor.yy303!=0 );
+ yymsp[-3].minor.yy41 = yymsp[-1].minor.yy41;
+ assert( yymsp[-3].minor.yy41!=0 );
}
break;
- case 323: /* over_clause ::= OVER nm */
+ case 340: /* over_clause ::= OVER nm */
{
- yymsp[-1].minor.yy303 = (Window*)sqlcipher_sqlite3DbMallocZero(pParse->db, sizeof(Window));
- if( yymsp[-1].minor.yy303 ){
- yymsp[-1].minor.yy303->zName = sqlcipher_sqlite3DbStrNDup(pParse->db, yymsp[0].minor.yy0.z, yymsp[0].minor.yy0.n);
+ yymsp[-1].minor.yy41 = (Window*)sqlcipher_sqlite3DbMallocZero(pParse->db, sizeof(Window));
+ if( yymsp[-1].minor.yy41 ){
+ yymsp[-1].minor.yy41->zName = sqlcipher_sqlite3DbStrNDup(pParse->db, yymsp[0].minor.yy0.z, yymsp[0].minor.yy0.n);
}
}
break;
- case 324: /* filter_clause ::= FILTER LP WHERE expr RP */
-{ yymsp[-4].minor.yy202 = yymsp[-1].minor.yy202; }
+ case 341: /* filter_clause ::= FILTER LP WHERE expr RP */
+{ yymsp[-4].minor.yy528 = yymsp[-1].minor.yy528; }
break;
default:
- /* (325) input ::= cmdlist */ yytestcase(yyruleno==325);
- /* (326) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==326);
- /* (327) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=327);
- /* (328) ecmd ::= SEMI */ yytestcase(yyruleno==328);
- /* (329) ecmd ::= cmdx SEMI */ yytestcase(yyruleno==329);
- /* (330) ecmd ::= explain cmdx SEMI (NEVER REDUCES) */ assert(yyruleno!=330);
- /* (331) trans_opt ::= */ yytestcase(yyruleno==331);
- /* (332) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==332);
- /* (333) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==333);
- /* (334) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==334);
- /* (335) savepoint_opt ::= */ yytestcase(yyruleno==335);
- /* (336) cmd ::= create_table create_table_args */ yytestcase(yyruleno==336);
- /* (337) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==337);
- /* (338) columnlist ::= columnname carglist */ yytestcase(yyruleno==338);
- /* (339) nm ::= ID|INDEXED */ yytestcase(yyruleno==339);
- /* (340) nm ::= STRING */ yytestcase(yyruleno==340);
- /* (341) nm ::= JOIN_KW */ yytestcase(yyruleno==341);
- /* (342) typetoken ::= typename */ yytestcase(yyruleno==342);
- /* (343) typename ::= ID|STRING */ yytestcase(yyruleno==343);
- /* (344) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=344);
- /* (345) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=345);
- /* (346) carglist ::= carglist ccons */ yytestcase(yyruleno==346);
- /* (347) carglist ::= */ yytestcase(yyruleno==347);
- /* (348) ccons ::= NULL onconf */ yytestcase(yyruleno==348);
- /* (349) ccons ::= GENERATED ALWAYS AS generated */ yytestcase(yyruleno==349);
- /* (350) ccons ::= AS generated */ yytestcase(yyruleno==350);
- /* (351) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==351);
- /* (352) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==352);
- /* (353) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=353);
- /* (354) tconscomma ::= */ yytestcase(yyruleno==354);
- /* (355) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=355);
- /* (356) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=356);
- /* (357) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=357);
- /* (358) oneselect ::= values */ yytestcase(yyruleno==358);
- /* (359) sclp ::= selcollist COMMA */ yytestcase(yyruleno==359);
- /* (360) as ::= ID|STRING */ yytestcase(yyruleno==360);
- /* (361) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=361);
- /* (362) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==362);
- /* (363) exprlist ::= nexprlist */ yytestcase(yyruleno==363);
- /* (364) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=364);
- /* (365) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=365);
- /* (366) nmnum ::= ON */ yytestcase(yyruleno==366);
- /* (367) nmnum ::= DELETE */ yytestcase(yyruleno==367);
- /* (368) nmnum ::= DEFAULT */ yytestcase(yyruleno==368);
- /* (369) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==369);
- /* (370) foreach_clause ::= */ yytestcase(yyruleno==370);
- /* (371) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==371);
- /* (372) trnm ::= nm */ yytestcase(yyruleno==372);
- /* (373) tridxby ::= */ yytestcase(yyruleno==373);
- /* (374) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==374);
- /* (375) database_kw_opt ::= */ yytestcase(yyruleno==375);
- /* (376) kwcolumn_opt ::= */ yytestcase(yyruleno==376);
- /* (377) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==377);
- /* (378) vtabarglist ::= vtabarg */ yytestcase(yyruleno==378);
- /* (379) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==379);
- /* (380) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==380);
- /* (381) anylist ::= */ yytestcase(yyruleno==381);
- /* (382) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==382);
- /* (383) anylist ::= anylist ANY */ yytestcase(yyruleno==383);
- /* (384) with ::= */ yytestcase(yyruleno==384);
+ /* (342) input ::= cmdlist */ yytestcase(yyruleno==342);
+ /* (343) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==343);
+ /* (344) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=344);
+ /* (345) ecmd ::= SEMI */ yytestcase(yyruleno==345);
+ /* (346) ecmd ::= cmdx SEMI */ yytestcase(yyruleno==346);
+ /* (347) ecmd ::= explain cmdx SEMI (NEVER REDUCES) */ assert(yyruleno!=347);
+ /* (348) trans_opt ::= */ yytestcase(yyruleno==348);
+ /* (349) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==349);
+ /* (350) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==350);
+ /* (351) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==351);
+ /* (352) savepoint_opt ::= */ yytestcase(yyruleno==352);
+ /* (353) cmd ::= create_table create_table_args */ yytestcase(yyruleno==353);
+ /* (354) table_option_set ::= table_option (OPTIMIZED OUT) */ assert(yyruleno!=354);
+ /* (355) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==355);
+ /* (356) columnlist ::= columnname carglist */ yytestcase(yyruleno==356);
+ /* (357) nm ::= ID|INDEXED */ yytestcase(yyruleno==357);
+ /* (358) nm ::= STRING */ yytestcase(yyruleno==358);
+ /* (359) nm ::= JOIN_KW */ yytestcase(yyruleno==359);
+ /* (360) typetoken ::= typename */ yytestcase(yyruleno==360);
+ /* (361) typename ::= ID|STRING */ yytestcase(yyruleno==361);
+ /* (362) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=362);
+ /* (363) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=363);
+ /* (364) carglist ::= carglist ccons */ yytestcase(yyruleno==364);
+ /* (365) carglist ::= */ yytestcase(yyruleno==365);
+ /* (366) ccons ::= NULL onconf */ yytestcase(yyruleno==366);
+ /* (367) ccons ::= GENERATED ALWAYS AS generated */ yytestcase(yyruleno==367);
+ /* (368) ccons ::= AS generated */ yytestcase(yyruleno==368);
+ /* (369) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==369);
+ /* (370) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==370);
+ /* (371) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=371);
+ /* (372) tconscomma ::= */ yytestcase(yyruleno==372);
+ /* (373) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=373);
+ /* (374) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=374);
+ /* (375) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=375);
+ /* (376) oneselect ::= values */ yytestcase(yyruleno==376);
+ /* (377) sclp ::= selcollist COMMA */ yytestcase(yyruleno==377);
+ /* (378) as ::= ID|STRING */ yytestcase(yyruleno==378);
+ /* (379) indexed_opt ::= indexed_by (OPTIMIZED OUT) */ assert(yyruleno!=379);
+ /* (380) returning ::= */ yytestcase(yyruleno==380);
+ /* (381) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=381);
+ /* (382) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==382);
+ /* (383) exprlist ::= nexprlist */ yytestcase(yyruleno==383);
+ /* (384) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=384);
+ /* (385) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=385);
+ /* (386) nmnum ::= ON */ yytestcase(yyruleno==386);
+ /* (387) nmnum ::= DELETE */ yytestcase(yyruleno==387);
+ /* (388) nmnum ::= DEFAULT */ yytestcase(yyruleno==388);
+ /* (389) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==389);
+ /* (390) foreach_clause ::= */ yytestcase(yyruleno==390);
+ /* (391) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==391);
+ /* (392) trnm ::= nm */ yytestcase(yyruleno==392);
+ /* (393) tridxby ::= */ yytestcase(yyruleno==393);
+ /* (394) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==394);
+ /* (395) database_kw_opt ::= */ yytestcase(yyruleno==395);
+ /* (396) kwcolumn_opt ::= */ yytestcase(yyruleno==396);
+ /* (397) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==397);
+ /* (398) vtabarglist ::= vtabarg */ yytestcase(yyruleno==398);
+ /* (399) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==399);
+ /* (400) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==400);
+ /* (401) anylist ::= */ yytestcase(yyruleno==401);
+ /* (402) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==402);
+ /* (403) anylist ::= anylist ANY */ yytestcase(yyruleno==403);
+ /* (404) with ::= */ yytestcase(yyruleno==404);
break;
/********** End reduce actions ************************************************/
};
@@ -164816,12 +174149,56 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Parser(
}
#endif
- do{
+ while(1){ /* Exit by "break" */
+ assert( yypParser->yytos>=yypParser->yystack );
assert( yyact==yypParser->yytos->stateno );
yyact = yy_find_shift_action((YYCODETYPE)yymajor,yyact);
if( yyact >= YY_MIN_REDUCE ){
- yyact = yy_reduce(yypParser,yyact-YY_MIN_REDUCE,yymajor,
- yyminor sqlcipher_sqlite3ParserCTX_PARAM);
+ unsigned int yyruleno = yyact - YY_MIN_REDUCE; /* Reduce by this rule */
+#ifndef NDEBUG
+ assert( yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) );
+ if( yyTraceFILE ){
+ int yysize = yyRuleInfoNRhs[yyruleno];
+ if( yysize ){
+ fprintf(yyTraceFILE, "%sReduce %d [%s]%s, pop back to state %d.\n",
+ yyTracePrompt,
+ yyruleno, yyRuleName[yyruleno],
+ yyruleno<YYNRULE_WITH_ACTION ? "" : " without external action",
+ yypParser->yytos[yysize].stateno);
+ }else{
+ fprintf(yyTraceFILE, "%sReduce %d [%s]%s.\n",
+ yyTracePrompt, yyruleno, yyRuleName[yyruleno],
+ yyruleno<YYNRULE_WITH_ACTION ? "" : " without external action");
+ }
+ }
+#endif /* NDEBUG */
+
+ /* Check that the stack is large enough to grow by a single entry
+ ** if the RHS of the rule is empty. This ensures that there is room
+ ** enough on the stack to push the LHS value */
+ if( yyRuleInfoNRhs[yyruleno]==0 ){
+#ifdef YYTRACKMAXSTACKDEPTH
+ if( (int)(yypParser->yytos - yypParser->yystack)>yypParser->yyhwm ){
+ yypParser->yyhwm++;
+ assert( yypParser->yyhwm ==
+ (int)(yypParser->yytos - yypParser->yystack));
+ }
+#endif
+#if YYSTACKDEPTH>0
+ if( yypParser->yytos>=yypParser->yystackEnd ){
+ yyStackOverflow(yypParser);
+ break;
+ }
+#else
+ if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz-1] ){
+ if( yyGrowStack(yypParser) ){
+ yyStackOverflow(yypParser);
+ break;
+ }
+ }
+#endif
+ }
+ yyact = yy_reduce(yypParser,yyruleno,yymajor,yyminor sqlcipher_sqlite3ParserCTX_PARAM);
}else if( yyact <= YY_MAX_SHIFTREDUCE ){
yy_shift(yypParser,yyact,(YYCODETYPE)yymajor,yyminor);
#ifndef YYNOERRORRECOVERY
@@ -164877,14 +174254,13 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Parser(
yy_destructor(yypParser, (YYCODETYPE)yymajor, &yyminorunion);
yymajor = YYNOCODE;
}else{
- while( yypParser->yytos >= yypParser->yystack
- && (yyact = yy_find_reduce_action(
- yypParser->yytos->stateno,
- YYERRORSYMBOL)) > YY_MAX_SHIFTREDUCE
- ){
+ while( yypParser->yytos > yypParser->yystack ){
+ yyact = yy_find_reduce_action(yypParser->yytos->stateno,
+ YYERRORSYMBOL);
+ if( yyact<=YY_MAX_SHIFTREDUCE ) break;
yy_pop_parser_stack(yypParser);
}
- if( yypParser->yytos < yypParser->yystack || yymajor==0 ){
+ if( yypParser->yytos <= yypParser->yystack || yymajor==0 ){
yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
yy_parse_failed(yypParser);
#ifndef YYNOERRORRECOVERY
@@ -164934,7 +174310,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Parser(
break;
#endif
}
- }while( yypParser->yytos>yypParser->yystack );
+ }
#ifndef NDEBUG
if( yyTraceFILE ){
yyStackEntry *i;
@@ -164995,8 +174371,8 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ParserFallback(int iToken){
** all of them need to be used within the switch.
*/
#define CC_X 0 /* The letter 'x', or start of BLOB literal */
-#define CC_KYWD 1 /* Alphabetics or '_'. Usable in a keyword */
-#define CC_ID 2 /* unicode characters usable in IDs */
+#define CC_KYWD0 1 /* First letter of a keyword */
+#define CC_KYWD 2 /* Alphabetics or '_'. Usable in a keyword */
#define CC_DIGIT 3 /* Digits */
#define CC_DOLLAR 4 /* '$' */
#define CC_VARALPHA 5 /* '@', '#', ':'. Alphabetic SQL variables */
@@ -165021,47 +174397,49 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ParserFallback(int iToken){
#define CC_AND 24 /* '&' */
#define CC_TILDA 25 /* '~' */
#define CC_DOT 26 /* '.' */
-#define CC_ILLEGAL 27 /* Illegal character */
-#define CC_NUL 28 /* 0x00 */
+#define CC_ID 27 /* unicode characters usable in IDs */
+#define CC_ILLEGAL 28 /* Illegal character */
+#define CC_NUL 29 /* 0x00 */
+#define CC_BOM 30 /* First byte of UTF8 BOM: 0xEF 0xBB 0xBF */
static const unsigned char aiClass[] = {
#ifdef SQLITE_ASCII
/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */
-/* 0x */ 28, 27, 27, 27, 27, 27, 27, 27, 27, 7, 7, 27, 7, 7, 27, 27,
-/* 1x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+/* 0x */ 29, 28, 28, 28, 28, 28, 28, 28, 28, 7, 7, 28, 7, 7, 28, 28,
+/* 1x */ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
/* 2x */ 7, 15, 8, 5, 4, 22, 24, 8, 17, 18, 21, 20, 23, 11, 26, 16,
/* 3x */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 19, 12, 14, 13, 6,
/* 4x */ 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-/* 5x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 9, 27, 27, 27, 1,
+/* 5x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 9, 28, 28, 28, 2,
/* 6x */ 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-/* 7x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 27, 10, 27, 25, 27,
-/* 8x */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-/* 9x */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-/* Ax */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-/* Bx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-/* Cx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-/* Dx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-/* Ex */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-/* Fx */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
+/* 7x */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 28, 10, 28, 25, 28,
+/* 8x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+/* 9x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+/* Ax */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+/* Bx */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+/* Cx */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+/* Dx */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+/* Ex */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 30,
+/* Fx */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27
#endif
#ifdef SQLITE_EBCDIC
/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf */
-/* 0x */ 27, 27, 27, 27, 27, 7, 27, 27, 27, 27, 27, 27, 7, 7, 27, 27,
-/* 1x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
-/* 2x */ 27, 27, 27, 27, 27, 7, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
-/* 3x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
-/* 4x */ 7, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 26, 12, 17, 20, 10,
-/* 5x */ 24, 27, 27, 27, 27, 27, 27, 27, 27, 27, 15, 4, 21, 18, 19, 27,
-/* 6x */ 11, 16, 27, 27, 27, 27, 27, 27, 27, 27, 27, 23, 22, 1, 13, 6,
-/* 7x */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 8, 5, 5, 5, 8, 14, 8,
-/* 8x */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27,
-/* 9x */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27,
-/* Ax */ 27, 25, 1, 1, 1, 1, 1, 0, 1, 1, 27, 27, 27, 27, 27, 27,
-/* Bx */ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 9, 27, 27, 27, 27, 27,
-/* Cx */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27,
-/* Dx */ 27, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 27, 27, 27, 27, 27,
-/* Ex */ 27, 27, 1, 1, 1, 1, 1, 0, 1, 1, 27, 27, 27, 27, 27, 27,
-/* Fx */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 27, 27, 27, 27, 27, 27,
+/* 0x */ 29, 28, 28, 28, 28, 7, 28, 28, 28, 28, 28, 28, 7, 7, 28, 28,
+/* 1x */ 28, 28, 28, 28, 28, 7, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+/* 2x */ 28, 28, 28, 28, 28, 7, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+/* 3x */ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+/* 4x */ 7, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 26, 12, 17, 20, 10,
+/* 5x */ 24, 28, 28, 28, 28, 28, 28, 28, 28, 28, 15, 4, 21, 18, 19, 28,
+/* 6x */ 11, 16, 28, 28, 28, 28, 28, 28, 28, 28, 28, 23, 22, 2, 13, 6,
+/* 7x */ 28, 28, 28, 28, 28, 28, 28, 28, 28, 8, 5, 5, 5, 8, 14, 8,
+/* 8x */ 28, 1, 1, 1, 1, 1, 1, 1, 1, 1, 28, 28, 28, 28, 28, 28,
+/* 9x */ 28, 1, 1, 1, 1, 1, 1, 1, 1, 1, 28, 28, 28, 28, 28, 28,
+/* Ax */ 28, 25, 1, 1, 1, 1, 1, 0, 2, 2, 28, 28, 28, 28, 28, 28,
+/* Bx */ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 9, 28, 28, 28, 28, 28,
+/* Cx */ 28, 1, 1, 1, 1, 1, 1, 1, 1, 1, 28, 28, 28, 28, 28, 28,
+/* Dx */ 28, 1, 1, 1, 1, 1, 1, 1, 1, 1, 28, 28, 28, 28, 28, 28,
+/* Ex */ 28, 28, 1, 1, 1, 1, 1, 0, 2, 2, 28, 28, 28, 28, 28, 28,
+/* Fx */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 28, 28, 28, 28, 28, 28,
#endif
};
@@ -165126,20 +174504,21 @@ const unsigned char ebcdicToAscii[] = {
** is substantially reduced. This is important for embedded applications
** on platforms with limited memory.
*/
-/* Hash score: 227 */
-/* zKWText[] encodes 984 bytes of keyword text in 648 bytes */
+/* Hash score: 231 */
+/* zKWText[] encodes 1007 bytes of keyword text in 667 bytes */
/* REINDEXEDESCAPEACHECKEYBEFOREIGNOREGEXPLAINSTEADDATABASELECT */
/* ABLEFTHENDEFERRABLELSEXCLUDELETEMPORARYISNULLSAVEPOINTERSECT */
/* IESNOTNULLIKEXCEPTRANSACTIONATURALTERAISEXCLUSIVEXISTS */
/* CONSTRAINTOFFSETRIGGERANGENERATEDETACHAVINGLOBEGINNEREFERENCES */
/* UNIQUERYWITHOUTERELEASEATTACHBETWEENOTHINGROUPSCASCADEFAULT */
/* CASECOLLATECREATECURRENT_DATEIMMEDIATEJOINSERTMATCHPLANALYZE */
-/* PRAGMABORTUPDATEVALUESVIRTUALWAYSWHENWHERECURSIVEAFTERENAMEAND */
-/* EFERREDISTINCTAUTOINCREMENTCASTCOLUMNCOMMITCONFLICTCROSS */
-/* CURRENT_TIMESTAMPARTITIONDROPRECEDINGFAILASTFILTEREPLACEFIRST */
-/* FOLLOWINGFROMFULLIMITIFORDERESTRICTOTHERSOVERIGHTROLLBACKROWS */
-/* UNBOUNDEDUNIONUSINGVACUUMVIEWINDOWBYINITIALLYPRIMARY */
-static const char zKWText[647] = {
+/* PRAGMATERIALIZEDEFERREDISTINCTUPDATEVALUESVIRTUALWAYSWHENWHERE */
+/* CURSIVEABORTAFTERENAMEANDROPARTITIONAUTOINCREMENTCASTCOLUMN */
+/* COMMITCONFLICTCROSSCURRENT_TIMESTAMPRECEDINGFAILASTFILTER */
+/* EPLACEFIRSTFOLLOWINGFROMFULLIMITIFORDERESTRICTOTHERSOVER */
+/* ETURNINGRIGHTROLLBACKROWSUNBOUNDEDUNIONUSINGVACUUMVIEWINDOWBY */
+/* INITIALLYPRIMARY */
+static const char zKWText[666] = {
'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',
@@ -165160,86 +174539,87 @@ static const char zKWText[647] = {
'C','R','E','A','T','E','C','U','R','R','E','N','T','_','D','A','T','E',
'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','U','P','D','A','T','E','V','A','L','U','E','S','V',
- 'I','R','T','U','A','L','W','A','Y','S','W','H','E','N','W','H','E','R',
- 'E','C','U','R','S','I','V','E','A','F','T','E','R','E','N','A','M','E',
- 'A','N','D','E','F','E','R','R','E','D','I','S','T','I','N','C','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','A','R','T','I','T','I','O','N','D','R','O','P','R','E',
- 'C','E','D','I','N','G','F','A','I','L','A','S','T','F','I','L','T','E',
- 'R','E','P','L','A','C','E','F','I','R','S','T','F','O','L','L','O','W',
- 'I','N','G','F','R','O','M','F','U','L','L','I','M','I','T','I','F','O',
- 'R','D','E','R','E','S','T','R','I','C','T','O','T','H','E','R','S','O',
- 'V','E','R','I','G','H','T','R','O','L','L','B','A','C','K','R','O','W',
- 'S','U','N','B','O','U','N','D','E','D','U','N','I','O','N','U','S','I',
- 'N','G','V','A','C','U','U','M','V','I','E','W','I','N','D','O','W','B',
- 'Y','I','N','I','T','I','A','L','L','Y','P','R','I','M','A','R','Y',
+ 'A','T','E','R','I','A','L','I','Z','E','D','E','F','E','R','R','E','D',
+ 'I','S','T','I','N','C','T','U','P','D','A','T','E','V','A','L','U','E',
+ 'S','V','I','R','T','U','A','L','W','A','Y','S','W','H','E','N','W','H',
+ 'E','R','E','C','U','R','S','I','V','E','A','B','O','R','T','A','F','T',
+ 'E','R','E','N','A','M','E','A','N','D','R','O','P','A','R','T','I','T',
+ 'I','O','N','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','E','C','E','D','I','N','G','F','A',
+ 'I','L','A','S','T','F','I','L','T','E','R','E','P','L','A','C','E','F',
+ 'I','R','S','T','F','O','L','L','O','W','I','N','G','F','R','O','M','F',
+ 'U','L','L','I','M','I','T','I','F','O','R','D','E','R','E','S','T','R',
+ 'I','C','T','O','T','H','E','R','S','O','V','E','R','E','T','U','R','N',
+ 'I','N','G','R','I','G','H','T','R','O','L','L','B','A','C','K','R','O',
+ 'W','S','U','N','B','O','U','N','D','E','D','U','N','I','O','N','U','S',
+ 'I','N','G','V','A','C','U','U','M','V','I','E','W','I','N','D','O','W',
+ 'B','Y','I','N','I','T','I','A','L','L','Y','P','R','I','M','A','R','Y',
};
/* aKWHash[i] is the hash value for the i-th keyword */
static const unsigned char aKWHash[127] = {
- 84, 102, 132, 82, 114, 29, 0, 0, 91, 0, 85, 72, 0,
- 53, 35, 86, 15, 0, 42, 94, 54, 126, 133, 19, 0, 0,
- 138, 0, 40, 128, 0, 22, 104, 0, 9, 0, 0, 122, 80,
- 0, 78, 6, 0, 65, 99, 145, 0, 134, 112, 0, 0, 48,
- 0, 100, 24, 0, 17, 0, 27, 70, 23, 26, 5, 60, 140,
- 107, 121, 0, 73, 101, 71, 143, 61, 119, 74, 0, 49, 0,
- 11, 41, 0, 110, 0, 0, 0, 106, 10, 108, 113, 124, 14,
- 50, 123, 0, 89, 0, 18, 120, 142, 56, 129, 137, 88, 83,
- 37, 30, 125, 0, 0, 105, 51, 130, 127, 0, 34, 0, 0,
- 44, 0, 95, 38, 39, 0, 20, 45, 116, 90,
+ 84, 92, 134, 82, 105, 29, 0, 0, 94, 0, 85, 72, 0,
+ 53, 35, 86, 15, 0, 42, 97, 54, 89, 135, 19, 0, 0,
+ 140, 0, 40, 129, 0, 22, 107, 0, 9, 0, 0, 123, 80,
+ 0, 78, 6, 0, 65, 103, 147, 0, 136, 115, 0, 0, 48,
+ 0, 90, 24, 0, 17, 0, 27, 70, 23, 26, 5, 60, 142,
+ 110, 122, 0, 73, 91, 71, 145, 61, 120, 74, 0, 49, 0,
+ 11, 41, 0, 113, 0, 0, 0, 109, 10, 111, 116, 125, 14,
+ 50, 124, 0, 100, 0, 18, 121, 144, 56, 130, 139, 88, 83,
+ 37, 30, 126, 0, 0, 108, 51, 131, 128, 0, 34, 0, 0,
+ 132, 0, 98, 38, 39, 0, 20, 45, 117, 93,
};
/* aKWNext[] forms the hash collision chain. If aKWHash[i]==0
** then the i-th keyword has no more hash collisions. Otherwise,
** the next keyword with the same hash is aKWHash[i]-1. */
-static const unsigned char aKWNext[145] = {
- 0, 0, 0, 0, 4, 0, 43, 0, 0, 103, 111, 0, 0,
- 0, 2, 0, 0, 141, 0, 0, 0, 13, 0, 0, 0, 0,
- 139, 0, 0, 118, 52, 0, 0, 135, 12, 0, 0, 62, 0,
- 136, 0, 131, 0, 0, 36, 0, 0, 28, 77, 0, 0, 0,
+static const unsigned char aKWNext[147] = {
+ 0, 0, 0, 0, 4, 0, 43, 0, 0, 106, 114, 0, 0,
+ 0, 2, 0, 0, 143, 0, 0, 0, 13, 0, 0, 0, 0,
+ 141, 0, 0, 119, 52, 0, 0, 137, 12, 0, 0, 62, 0,
+ 138, 0, 133, 0, 0, 36, 0, 0, 28, 77, 0, 0, 0,
0, 59, 0, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 69, 0, 0, 0, 0, 0, 144, 3, 0, 58, 0, 1,
- 75, 0, 0, 0, 31, 0, 0, 0, 0, 0, 0, 64, 66,
- 63, 0, 0, 0, 0, 46, 0, 16, 0, 115, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 81, 97, 0, 8, 0, 109,
- 21, 7, 67, 0, 79, 93, 117, 0, 0, 68, 0, 0, 96,
- 0, 55, 0, 76, 0, 92, 32, 33, 57, 25, 0, 98, 0,
- 0, 87,
+ 0, 69, 0, 0, 0, 0, 0, 146, 3, 0, 58, 0, 1,
+ 75, 0, 0, 0, 31, 0, 0, 0, 0, 0, 127, 0, 104,
+ 0, 64, 66, 63, 0, 0, 0, 0, 0, 46, 0, 16, 8,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 101, 0,
+ 112, 21, 7, 67, 0, 79, 96, 118, 0, 0, 68, 0, 0,
+ 99, 44, 0, 55, 0, 76, 0, 95, 32, 33, 57, 25, 0,
+ 102, 0, 0, 87,
};
/* aKWLen[i] is the length (in bytes) of the i-th keyword */
-static const unsigned char aKWLen[145] = {
+static const unsigned char aKWLen[147] = {
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, 7,
6, 9, 4, 2, 6, 5, 9, 9, 4, 7, 3, 2, 4,
4, 6, 11, 6, 2, 7, 5, 5, 9, 6, 10, 4, 6,
2, 3, 7, 5, 9, 6, 6, 4, 5, 5, 10, 6, 5,
7, 4, 5, 7, 6, 7, 7, 6, 5, 7, 3, 7, 4,
- 7, 6, 12, 9, 4, 6, 5, 4, 7, 6, 5, 6, 6,
- 7, 6, 4, 5, 9, 5, 6, 3, 8, 8, 2, 13, 2,
- 2, 4, 6, 6, 8, 5, 17, 12, 7, 9, 4, 9, 4,
- 4, 6, 7, 5, 9, 4, 4, 5, 2, 5, 8, 6, 4,
- 5, 8, 4, 3, 9, 5, 5, 6, 4, 6, 2, 2, 9,
- 3, 7,
+ 7, 6, 12, 9, 4, 6, 5, 4, 7, 6, 12, 8, 8,
+ 2, 6, 6, 7, 6, 4, 5, 9, 5, 5, 6, 3, 4,
+ 9, 13, 2, 2, 4, 6, 6, 8, 5, 17, 12, 7, 9,
+ 4, 4, 6, 7, 5, 9, 4, 4, 5, 2, 5, 8, 6,
+ 4, 9, 5, 8, 4, 3, 9, 5, 5, 6, 4, 6, 2,
+ 2, 9, 3, 7,
};
/* aKWOffset[i] is the index into zKWText[] of the start of
** the text for the i-th keyword. */
-static const unsigned short int aKWOffset[145] = {
+static const unsigned short int aKWOffset[147] = {
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, 90, 90, 94, 99, 101, 105, 111, 119, 123, 123, 123, 126,
129, 132, 137, 142, 146, 147, 152, 156, 160, 168, 174, 181, 184,
184, 187, 189, 195, 198, 206, 211, 216, 219, 222, 226, 236, 239,
244, 244, 248, 252, 259, 265, 271, 277, 277, 283, 284, 288, 295,
- 299, 306, 312, 324, 333, 335, 341, 346, 348, 355, 360, 365, 371,
- 377, 382, 388, 392, 395, 404, 408, 414, 416, 423, 424, 431, 433,
- 435, 444, 448, 454, 460, 468, 473, 473, 473, 489, 498, 501, 510,
- 513, 517, 522, 529, 534, 543, 547, 550, 555, 557, 561, 569, 575,
- 578, 583, 591, 591, 595, 604, 609, 614, 620, 623, 626, 629, 631,
- 636, 640,
+ 299, 306, 312, 324, 333, 335, 341, 346, 348, 355, 359, 370, 377,
+ 378, 385, 391, 397, 402, 408, 412, 415, 424, 429, 433, 439, 441,
+ 444, 453, 455, 457, 466, 470, 476, 482, 490, 495, 495, 495, 511,
+ 520, 523, 527, 532, 539, 544, 553, 557, 560, 565, 567, 571, 579,
+ 585, 588, 597, 602, 610, 610, 614, 623, 628, 633, 639, 642, 645,
+ 648, 650, 655, 659,
};
/* aKWCode[i] is the parser symbol code for the i-th keyword */
-static const unsigned char aKWCode[145] = {
+static const unsigned char aKWCode[147] = {
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,
@@ -165257,18 +174637,19 @@ static const unsigned char aKWCode[145] = {
TK_BETWEEN, TK_NOTHING, TK_GROUPS, TK_GROUP, TK_CASCADE,
TK_ASC, TK_DEFAULT, TK_CASE, TK_COLLATE, TK_CREATE,
TK_CTIME_KW, TK_IMMEDIATE, TK_JOIN, TK_INSERT, TK_MATCH,
- TK_PLAN, TK_ANALYZE, TK_PRAGMA, TK_ABORT, TK_UPDATE,
- TK_VALUES, TK_VIRTUAL, TK_ALWAYS, TK_WHEN, TK_WHERE,
- TK_RECURSIVE, TK_AFTER, TK_RENAME, TK_AND, TK_DEFERRED,
- TK_DISTINCT, TK_IS, TK_AUTOINCR, TK_TO, TK_IN,
- TK_CAST, TK_COLUMNKW, TK_COMMIT, TK_CONFLICT, TK_JOIN_KW,
- TK_CTIME_KW, TK_CTIME_KW, TK_CURRENT, TK_PARTITION, TK_DROP,
- TK_PRECEDING, TK_FAIL, TK_LAST, TK_FILTER, TK_REPLACE,
- TK_FIRST, TK_FOLLOWING, TK_FROM, TK_JOIN_KW, TK_LIMIT,
- TK_IF, TK_ORDER, TK_RESTRICT, TK_OTHERS, TK_OVER,
- TK_JOIN_KW, TK_ROLLBACK, TK_ROWS, TK_ROW, TK_UNBOUNDED,
- TK_UNION, TK_USING, TK_VACUUM, TK_VIEW, TK_WINDOW,
- TK_DO, TK_BY, TK_INITIALLY, TK_ALL, TK_PRIMARY,
+ TK_PLAN, TK_ANALYZE, TK_PRAGMA, TK_MATERIALIZED, TK_DEFERRED,
+ TK_DISTINCT, TK_IS, TK_UPDATE, TK_VALUES, TK_VIRTUAL,
+ TK_ALWAYS, TK_WHEN, TK_WHERE, TK_RECURSIVE, TK_ABORT,
+ TK_AFTER, TK_RENAME, TK_AND, TK_DROP, TK_PARTITION,
+ TK_AUTOINCR, TK_TO, TK_IN, TK_CAST, TK_COLUMNKW,
+ TK_COMMIT, TK_CONFLICT, TK_JOIN_KW, TK_CTIME_KW, TK_CTIME_KW,
+ TK_CURRENT, TK_PRECEDING, TK_FAIL, TK_LAST, TK_FILTER,
+ TK_REPLACE, TK_FIRST, TK_FOLLOWING, TK_FROM, TK_JOIN_KW,
+ TK_LIMIT, TK_IF, TK_ORDER, TK_RESTRICT, TK_OTHERS,
+ TK_OVER, TK_RETURNING, TK_JOIN_KW, TK_ROLLBACK, TK_ROWS,
+ TK_ROW, TK_UNBOUNDED, TK_UNION, TK_USING, TK_VACUUM,
+ TK_VIEW, TK_WINDOW, TK_DO, TK_BY, TK_INITIALLY,
+ TK_ALL, TK_PRIMARY,
};
/* Hash table decoded:
** 0: INSERT
@@ -165292,7 +174673,7 @@ static const unsigned char aKWCode[145] = {
** 18: TRANSACTION RIGHT
** 19: WHEN
** 20: SET HAVING
-** 21: IF
+** 21: MATERIALIZED IF
** 22: ROWS
** 23: SELECT
** 24:
@@ -165388,7 +174769,7 @@ static const unsigned char aKWCode[145] = {
** 114: INTERSECT UNBOUNDED
** 115:
** 116:
-** 117: ON
+** 117: RETURNING ON
** 118:
** 119: WHERE
** 120: NO INNER
@@ -165406,7 +174787,7 @@ static int keywordCode(const char *z, int n, int *pType){
int i, j;
const char *zKW;
if( n>=2 ){
- i = ((charMap(z[0])*4) ^ (charMap(z[n-1])*3) ^ n) % 127;
+ i = ((charMap(z[0])*4) ^ (charMap(z[n-1])*3) ^ n*1) % 127;
for(i=((int)aKWHash[i])-1; i>=0; i=((int)aKWNext[i])-1){
if( aKWLen[i]!=n ) continue;
zKW = &zKWText[aKWOffset[i]];
@@ -165511,63 +174892,65 @@ static int keywordCode(const char *z, int n, int *pType){
testcase( i==85 ); /* PLAN */
testcase( i==86 ); /* ANALYZE */
testcase( i==87 ); /* PRAGMA */
- testcase( i==88 ); /* ABORT */
- testcase( i==89 ); /* UPDATE */
- testcase( i==90 ); /* VALUES */
- testcase( i==91 ); /* VIRTUAL */
- testcase( i==92 ); /* ALWAYS */
- testcase( i==93 ); /* WHEN */
- testcase( i==94 ); /* WHERE */
- testcase( i==95 ); /* RECURSIVE */
- testcase( i==96 ); /* AFTER */
- testcase( i==97 ); /* RENAME */
- testcase( i==98 ); /* AND */
- testcase( i==99 ); /* DEFERRED */
- testcase( i==100 ); /* DISTINCT */
- testcase( i==101 ); /* IS */
- testcase( i==102 ); /* AUTOINCREMENT */
- testcase( i==103 ); /* TO */
- testcase( i==104 ); /* IN */
- testcase( i==105 ); /* CAST */
- testcase( i==106 ); /* COLUMN */
- testcase( i==107 ); /* COMMIT */
- testcase( i==108 ); /* CONFLICT */
- testcase( i==109 ); /* CROSS */
- testcase( i==110 ); /* CURRENT_TIMESTAMP */
- testcase( i==111 ); /* CURRENT_TIME */
- testcase( i==112 ); /* CURRENT */
- testcase( i==113 ); /* PARTITION */
- testcase( i==114 ); /* DROP */
- testcase( i==115 ); /* PRECEDING */
- testcase( i==116 ); /* FAIL */
- testcase( i==117 ); /* LAST */
- testcase( i==118 ); /* FILTER */
- testcase( i==119 ); /* REPLACE */
- testcase( i==120 ); /* FIRST */
- testcase( i==121 ); /* FOLLOWING */
- testcase( i==122 ); /* FROM */
- testcase( i==123 ); /* FULL */
- testcase( i==124 ); /* LIMIT */
- testcase( i==125 ); /* IF */
- testcase( i==126 ); /* ORDER */
- testcase( i==127 ); /* RESTRICT */
- testcase( i==128 ); /* OTHERS */
- testcase( i==129 ); /* OVER */
- testcase( i==130 ); /* RIGHT */
- testcase( i==131 ); /* ROLLBACK */
- testcase( i==132 ); /* ROWS */
- testcase( i==133 ); /* ROW */
- testcase( i==134 ); /* UNBOUNDED */
- testcase( i==135 ); /* UNION */
- testcase( i==136 ); /* USING */
- testcase( i==137 ); /* VACUUM */
- testcase( i==138 ); /* VIEW */
- testcase( i==139 ); /* WINDOW */
- testcase( i==140 ); /* DO */
- testcase( i==141 ); /* BY */
- testcase( i==142 ); /* INITIALLY */
- testcase( i==143 ); /* ALL */
- testcase( i==144 ); /* PRIMARY */
+ testcase( i==88 ); /* MATERIALIZED */
+ testcase( i==89 ); /* DEFERRED */
+ testcase( i==90 ); /* DISTINCT */
+ testcase( i==91 ); /* IS */
+ testcase( i==92 ); /* UPDATE */
+ testcase( i==93 ); /* VALUES */
+ testcase( i==94 ); /* VIRTUAL */
+ testcase( i==95 ); /* ALWAYS */
+ testcase( i==96 ); /* WHEN */
+ testcase( i==97 ); /* WHERE */
+ testcase( i==98 ); /* RECURSIVE */
+ testcase( i==99 ); /* ABORT */
+ testcase( i==100 ); /* AFTER */
+ testcase( i==101 ); /* RENAME */
+ testcase( i==102 ); /* AND */
+ testcase( i==103 ); /* DROP */
+ testcase( i==104 ); /* PARTITION */
+ testcase( i==105 ); /* AUTOINCREMENT */
+ testcase( i==106 ); /* TO */
+ testcase( i==107 ); /* IN */
+ testcase( i==108 ); /* CAST */
+ testcase( i==109 ); /* COLUMN */
+ testcase( i==110 ); /* COMMIT */
+ testcase( i==111 ); /* CONFLICT */
+ testcase( i==112 ); /* CROSS */
+ testcase( i==113 ); /* CURRENT_TIMESTAMP */
+ testcase( i==114 ); /* CURRENT_TIME */
+ testcase( i==115 ); /* CURRENT */
+ testcase( i==116 ); /* PRECEDING */
+ testcase( i==117 ); /* FAIL */
+ testcase( i==118 ); /* LAST */
+ testcase( i==119 ); /* FILTER */
+ testcase( i==120 ); /* REPLACE */
+ testcase( i==121 ); /* FIRST */
+ testcase( i==122 ); /* FOLLOWING */
+ testcase( i==123 ); /* FROM */
+ testcase( i==124 ); /* FULL */
+ testcase( i==125 ); /* LIMIT */
+ testcase( i==126 ); /* IF */
+ testcase( i==127 ); /* ORDER */
+ testcase( i==128 ); /* RESTRICT */
+ testcase( i==129 ); /* OTHERS */
+ testcase( i==130 ); /* OVER */
+ testcase( i==131 ); /* RETURNING */
+ testcase( i==132 ); /* RIGHT */
+ testcase( i==133 ); /* ROLLBACK */
+ testcase( i==134 ); /* ROWS */
+ testcase( i==135 ); /* ROW */
+ testcase( i==136 ); /* UNBOUNDED */
+ testcase( i==137 ); /* UNION */
+ testcase( i==138 ); /* USING */
+ testcase( i==139 ); /* VACUUM */
+ testcase( i==140 ); /* VIEW */
+ testcase( i==141 ); /* WINDOW */
+ testcase( i==142 ); /* DO */
+ testcase( i==143 ); /* BY */
+ testcase( i==144 ); /* INITIALLY */
+ testcase( i==145 ); /* ALL */
+ testcase( i==146 ); /* PRIMARY */
*pType = aKWCode[i];
break;
}
@@ -165579,7 +174962,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3KeywordCode(const unsigned char *z, int n){
keywordCode((char*)z, n, &id);
return id;
}
-#define SQLITE_N_KEYWORD 145
+#define SQLITE_N_KEYWORD 147
SQLITE_API int sqlcipher_sqlite3_keyword_name(int i,const char **pzName,int *pnName){
if( i<0 || i>=SQLITE_N_KEYWORD ) return SQLITE_ERROR;
*pzName = zKWText + aKWOffset[i];
@@ -165737,6 +175120,9 @@ SQLITE_PRIVATE int sqlcipher_sqlite3GetToken(const unsigned char *z, int *tokenT
for(i=2; (c=z[i])!=0 && c!='\n'; i++){}
*tokenType = TK_SPACE; /* IMP: R-22934-25134 */
return i;
+ }else if( z[1]=='>' ){
+ *tokenType = TK_PTR;
+ return 2 + (z[2]=='>');
}
*tokenType = TK_MINUS;
return 1;
@@ -165948,7 +175334,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3GetToken(const unsigned char *z, int *tokenT
if( n==0 ) *tokenType = TK_ILLEGAL;
return i;
}
- case CC_KYWD: {
+ case CC_KYWD0: {
for(i=1; aiClass[z[i]]<=CC_KYWD; i++){}
if( IdChar(z[i]) ){
/* This token started out using characters that can appear in keywords,
@@ -165978,10 +175364,19 @@ SQLITE_PRIVATE int sqlcipher_sqlite3GetToken(const unsigned char *z, int *tokenT
** SQL keywords start with the letter 'x'. Fall through */
/* no break */ deliberate_fall_through
}
+ case CC_KYWD:
case CC_ID: {
i = 1;
break;
}
+ case CC_BOM: {
+ if( z[1]==0xbb && z[2]==0xbf ){
+ *tokenType = TK_SPACE;
+ return 3;
+ }
+ i = 1;
+ break;
+ }
case CC_NUL: {
*tokenType = TK_ILLEGAL;
return 0;
@@ -165997,13 +175392,9 @@ SQLITE_PRIVATE int sqlcipher_sqlite3GetToken(const unsigned char *z, int *tokenT
}
/*
-** Run the parser on the given SQL string. The parser structure is
-** passed in. An SQLITE_ status code is returned. If an error occurs
-** then an and attempt is made to write an error message into
-** memory obtained from sqlcipher_sqlite3_malloc() and to make *pzErrMsg point to that
-** error message.
+** Run the parser on the given SQL string.
*/
-SQLITE_PRIVATE int sqlcipher_sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
+SQLITE_PRIVATE int sqlcipher_sqlite3RunParser(Parse *pParse, const char *zSql){
int nErr = 0; /* Number of errors encountered */
void *pEngine; /* The LEMON-generated LALR(1) parser */
int n = 0; /* Length of the next token token */
@@ -166011,6 +175402,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3RunParser(Parse *pParse, const char *zSql, c
int lastTokenParsed = -1; /* type of the previous token */
sqlcipher_sqlite3 *db = pParse->db; /* The database connection */
int mxSqlLen; /* Max length of an SQL string */
+ Parse *pParentParse = 0; /* Outer parse context, if any */
#ifdef sqlcipher_sqlite3Parser_ENGINEALWAYSONSTACK
yyParser sEngine; /* Space to hold the Lemon-generated Parser object */
#endif
@@ -166023,7 +175415,6 @@ SQLITE_PRIVATE int sqlcipher_sqlite3RunParser(Parse *pParse, const char *zSql, c
}
pParse->rc = SQLITE_OK;
pParse->zTail = zSql;
- assert( pzErrMsg!=0 );
#ifdef SQLITE_DEBUG
if( db->flags & SQLITE_ParserTrace ){
printf("parser: [[[%s]]]\n", zSql);
@@ -166046,13 +175437,14 @@ SQLITE_PRIVATE int sqlcipher_sqlite3RunParser(Parse *pParse, const char *zSql, c
assert( pParse->pNewTrigger==0 );
assert( pParse->nVar==0 );
assert( pParse->pVList==0 );
- pParse->pParentParse = db->pParse;
+ pParentParse = db->pParse;
db->pParse = pParse;
while( 1 ){
n = sqlcipher_sqlite3GetToken((u8*)zSql, &tokenType);
mxSqlLen -= n;
if( mxSqlLen<0 ){
pParse->rc = SQLITE_TOOBIG;
+ pParse->nErr++;
break;
}
#ifndef SQLITE_OMIT_WINDOWFUNC
@@ -166066,6 +175458,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3RunParser(Parse *pParse, const char *zSql, c
#endif /* SQLITE_OMIT_WINDOWFUNC */
if( AtomicLoad(&db->u1.isInterrupted) ){
pParse->rc = SQLITE_INTERRUPT;
+ pParse->nErr++;
break;
}
if( tokenType==TK_SPACE ){
@@ -166095,7 +175488,10 @@ SQLITE_PRIVATE int sqlcipher_sqlite3RunParser(Parse *pParse, const char *zSql, c
tokenType = analyzeFilterKeyword((const u8*)&zSql[6], lastTokenParsed);
#endif /* SQLITE_OMIT_WINDOWFUNC */
}else{
- sqlcipher_sqlite3ErrorMsg(pParse, "unrecognized token: \"%.*s\"", n, zSql);
+ Token x;
+ x.z = zSql;
+ x.n = n;
+ sqlcipher_sqlite3ErrorMsg(pParse, "unrecognized token: \"%T\"", &x);
break;
}
}
@@ -166123,58 +175519,30 @@ SQLITE_PRIVATE int sqlcipher_sqlite3RunParser(Parse *pParse, const char *zSql, c
if( db->mallocFailed ){
pParse->rc = SQLITE_NOMEM_BKPT;
}
- if( pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE && pParse->zErrMsg==0 ){
- pParse->zErrMsg = sqlcipher_sqlite3MPrintf(db, "%s", sqlcipher_sqlite3ErrStr(pParse->rc));
- }
- assert( pzErrMsg!=0 );
- if( pParse->zErrMsg ){
- *pzErrMsg = pParse->zErrMsg;
- sqlcipher_sqlite3_log(pParse->rc, "%s in \"%s\"",
- *pzErrMsg, pParse->zTail);
- pParse->zErrMsg = 0;
+ if( pParse->zErrMsg || (pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE) ){
+ if( pParse->zErrMsg==0 ){
+ pParse->zErrMsg = sqlcipher_sqlite3MPrintf(db, "%s", sqlcipher_sqlite3ErrStr(pParse->rc));
+ }
+ sqlcipher_sqlite3_log(pParse->rc, "%s in \"%s\"", pParse->zErrMsg, pParse->zTail);
nErr++;
}
pParse->zTail = zSql;
- if( pParse->pVdbe && pParse->nErr>0 && pParse->nested==0 ){
- sqlcipher_sqlite3VdbeDelete(pParse->pVdbe);
- pParse->pVdbe = 0;
- }
-#ifndef SQLITE_OMIT_SHARED_CACHE
- if( pParse->nested==0 ){
- sqlcipher_sqlite3DbFree(db, pParse->aTableLock);
- pParse->aTableLock = 0;
- pParse->nTableLock = 0;
- }
-#endif
#ifndef SQLITE_OMIT_VIRTUALTABLE
sqlcipher_sqlite3_free(pParse->apVtabLock);
#endif
- if( !IN_SPECIAL_PARSE ){
+ if( pParse->pNewTable && !IN_SPECIAL_PARSE ){
/* If the pParse->declareVtab flag is set, do not delete any table
** structure built up in pParse->pNewTable. The calling code (see vtab.c)
** will take responsibility for freeing the Table structure.
*/
sqlcipher_sqlite3DeleteTable(db, pParse->pNewTable);
}
- if( !IN_RENAME_OBJECT ){
+ if( pParse->pNewTrigger && !IN_RENAME_OBJECT ){
sqlcipher_sqlite3DeleteTrigger(db, pParse->pNewTrigger);
}
-
- if( pParse->pWithToFree ) sqlcipher_sqlite3WithDelete(db, pParse->pWithToFree);
- sqlcipher_sqlite3DbFree(db, pParse->pVList);
- while( pParse->pAinc ){
- AutoincInfo *p = pParse->pAinc;
- pParse->pAinc = p->pNext;
- sqlcipher_sqlite3DbFreeNN(db, p);
- }
- while( pParse->pZombieTab ){
- Table *p = pParse->pZombieTab;
- pParse->pZombieTab = p->pNextZombie;
- sqlcipher_sqlite3DeleteTable(db, p);
- }
- db->pParse = pParse->pParentParse;
- pParse->pParentParse = 0;
+ if( pParse->pVList ) sqlcipher_sqlite3DbFreeNN(db, pParse->pVList);
+ db->pParse = pParentParse;
assert( nErr==0 || pParse->rc!=SQLITE_OK );
return nErr;
}
@@ -166755,9 +176123,6 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Fts2Init(sqlcipher_sqlite3*);
#ifdef SQLITE_ENABLE_FTS5
SQLITE_PRIVATE int sqlcipher_sqlite3Fts5Init(sqlcipher_sqlite3*);
#endif
-#ifdef SQLITE_ENABLE_JSON1
-SQLITE_PRIVATE int sqlcipher_sqlite3Json1Init(sqlcipher_sqlite3*);
-#endif
#ifdef SQLITE_ENABLE_STMTVTAB
SQLITE_PRIVATE int sqlcipher_sqlite3StmtVtabInit(sqlcipher_sqlite3*);
#endif
@@ -166792,8 +176157,8 @@ static int (*const sqlcipher_sqlite3BuiltinExtensions[])(sqlcipher_sqlite3*) = {
sqlcipher_sqlite3DbstatRegister,
#endif
sqlcipher_sqlite3TestExtInit,
-#ifdef SQLITE_ENABLE_JSON1
- sqlcipher_sqlite3Json1Init,
+#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_JSON)
+ sqlcipher_sqlite3JsonTableFunctions,
#endif
#ifdef SQLITE_ENABLE_STMTVTAB
sqlcipher_sqlite3StmtVtabInit,
@@ -167010,7 +176375,7 @@ SQLITE_API int sqlcipher_sqlite3_initialize(void){
sqlcipher_sqlite3GlobalConfig.isPCacheInit = 1;
rc = sqlcipher_sqlite3OsInit();
}
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
if( rc==SQLITE_OK ){
rc = sqlcipher_sqlite3MemdbInit();
}
@@ -167425,12 +176790,12 @@ SQLITE_API int sqlcipher_sqlite3_config(int op, ...){
}
#endif /* SQLITE_ENABLE_SORTER_REFERENCES */
-#ifdef SQLITE_ENABLE_DESERIALIZE
+#ifndef SQLITE_OMIT_DESERIALIZE
case SQLITE_CONFIG_MEMDB_MAXSIZE: {
sqlcipher_sqlite3GlobalConfig.mxMemdbSize = va_arg(ap, sqlcipher_sqlite3_int64);
break;
}
-#endif /* SQLITE_ENABLE_DESERIALIZE */
+#endif /* SQLITE_OMIT_DESERIALIZE */
default: {
rc = SQLITE_ERROR;
@@ -167791,7 +177156,7 @@ SQLITE_API void sqlcipher_sqlite3_set_last_insert_rowid(sqlcipher_sqlite3 *db, s
/*
** Return the number of changes in the most recent call to sqlcipher_sqlite3_exec().
*/
-SQLITE_API int sqlcipher_sqlite3_changes(sqlcipher_sqlite3 *db){
+SQLITE_API sqlcipher_sqlite3_int64 sqlcipher_sqlite3_changes64(sqlcipher_sqlite3 *db){
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlcipher_sqlite3SafetyCheckOk(db) ){
(void)SQLITE_MISUSE_BKPT;
@@ -167800,11 +177165,14 @@ SQLITE_API int sqlcipher_sqlite3_changes(sqlcipher_sqlite3 *db){
#endif
return db->nChange;
}
+SQLITE_API int sqlcipher_sqlite3_changes(sqlcipher_sqlite3 *db){
+ return (int)sqlcipher_sqlite3_changes64(db);
+}
/*
** Return the number of changes since the database handle was opened.
*/
-SQLITE_API int sqlcipher_sqlite3_total_changes(sqlcipher_sqlite3 *db){
+SQLITE_API sqlcipher_sqlite3_int64 sqlcipher_sqlite3_total_changes64(sqlcipher_sqlite3 *db){
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlcipher_sqlite3SafetyCheckOk(db) ){
(void)SQLITE_MISUSE_BKPT;
@@ -167813,6 +177181,9 @@ SQLITE_API int sqlcipher_sqlite3_total_changes(sqlcipher_sqlite3 *db){
#endif
return db->nTotalChange;
}
+SQLITE_API int sqlcipher_sqlite3_total_changes(sqlcipher_sqlite3 *db){
+ return (int)sqlcipher_sqlite3_total_changes64(db);
+}
/*
** Close all open savepoints. This function only manipulates fields of the
@@ -167837,7 +177208,9 @@ SQLITE_PRIVATE void sqlcipher_sqlite3CloseSavepoints(sqlcipher_sqlite3 *db){
** with SQLITE_ANY as the encoding.
*/
static void functionDestroy(sqlcipher_sqlite3 *db, FuncDef *p){
- FuncDestructor *pDestructor = p->u.pDestructor;
+ FuncDestructor *pDestructor;
+ assert( (p->funcFlags & SQLITE_FUNC_BUILTIN)==0 );
+ pDestructor = p->u.pDestructor;
if( pDestructor ){
pDestructor->nRef--;
if( pDestructor->nRef==0 ){
@@ -167941,7 +177314,7 @@ static int sqlcipher_sqlite3Close(sqlcipher_sqlite3 *db, int forceZombie){
/* Convert the connection into a zombie and then close it.
*/
- db->magic = SQLITE_MAGIC_ZOMBIE;
+ db->eOpenState = SQLITE_STATE_ZOMBIE;
sqlcipher_sqlite3LeaveMutexAndCloseZombie(db);
return SQLITE_OK;
}
@@ -167979,7 +177352,7 @@ SQLITE_API int sqlcipher_sqlite3_txn_state(sqlcipher_sqlite3 *db, const char *zS
/*
** Two variations on the public interface for closing a database
** connection. The sqlcipher_sqlite3_close() version returns SQLITE_BUSY and
-** leaves the connection option if there are unfinalized prepared
+** leaves the connection open if there are unfinalized prepared
** statements or unfinished sqlcipher_sqlite3_backups. The sqlcipher_sqlite3_close_v2()
** version forces the connection to become a zombie if there are
** unclosed resources, and arranges for deallocation when the last
@@ -168005,7 +177378,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3LeaveMutexAndCloseZombie(sqlcipher_sqlite3
** or if the connection has not yet been closed by sqlcipher_sqlite3_close_v2(),
** then just leave the mutex and return.
*/
- if( db->magic!=SQLITE_MAGIC_ZOMBIE || connectionIsBusy(db) ){
+ if( db->eOpenState!=SQLITE_STATE_ZOMBIE || connectionIsBusy(db) ){
sqlcipher_sqlite3_mutex_leave(db->mutex);
return;
}
@@ -168091,7 +177464,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3LeaveMutexAndCloseZombie(sqlcipher_sqlite3
sqlcipher_sqlite3_free(db->auth.zAuthPW);
#endif
- db->magic = SQLITE_MAGIC_ERROR;
+ db->eOpenState = SQLITE_STATE_ERROR;
/* The temp-database schema is allocated differently from the other schema
** objects (using sqliteMalloc() directly, instead of sqlcipher_sqlite3BtreeSchema()).
@@ -168100,8 +177473,11 @@ SQLITE_PRIVATE void sqlcipher_sqlite3LeaveMutexAndCloseZombie(sqlcipher_sqlite3
** structure?
*/
sqlcipher_sqlite3DbFree(db, db->aDb[1].pSchema);
+ if( db->xAutovacDestr ){
+ db->xAutovacDestr(db->pAutovacPagesArg);
+ }
sqlcipher_sqlite3_mutex_leave(db->mutex);
- db->magic = SQLITE_MAGIC_CLOSED;
+ db->eOpenState = SQLITE_STATE_CLOSED;
sqlcipher_sqlite3_mutex_free(db->mutex);
assert( sqlcipher_sqlite3LookasideUsed(db,0)==0 );
if( db->lookaside.bMalloced ){
@@ -168154,7 +177530,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3RollbackAll(sqlcipher_sqlite3 *db, int trip
/* Any deferred constraint violations have now been resolved. */
db->nDeferredCons = 0;
db->nDeferredImmCons = 0;
- db->flags &= ~(u64)SQLITE_DeferFKs;
+ db->flags &= ~(u64)(SQLITE_DeferFKs|SQLITE_CorruptRdOnly);
/* If one has been configured, invoke the rollback-hook callback */
if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){
@@ -168489,7 +177865,7 @@ SQLITE_API int sqlcipher_sqlite3_busy_timeout(sqlcipher_sqlite3 *db, int ms){
*/
SQLITE_API void sqlcipher_sqlite3_interrupt(sqlcipher_sqlite3 *db){
#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlcipher_sqlite3SafetyCheckOk(db) && (db==0 || db->magic!=SQLITE_MAGIC_ZOMBIE) ){
+ if( !sqlcipher_sqlite3SafetyCheckOk(db) && (db==0 || db->eOpenState!=SQLITE_STATE_ZOMBIE) ){
(void)SQLITE_MISUSE_BKPT;
return;
}
@@ -168518,7 +177894,6 @@ SQLITE_PRIVATE int sqlcipher_sqlite3CreateFunc(
FuncDestructor *pDestructor
){
FuncDef *p;
- int nName;
int extraFlags;
assert( sqlcipher_sqlite3_mutex_held(db->mutex) );
@@ -168528,7 +177903,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3CreateFunc(
|| ((xFinal==0)!=(xStep==0)) /* Both or neither of xFinal and xStep */
|| ((xValue==0)!=(xInverse==0)) /* Both or neither of xValue, xInverse */
|| (nArg<-1 || nArg>SQLITE_MAX_FUNCTION_ARG)
- || (255<(nName = sqlcipher_sqlite3Strlen30( zFunctionName)))
+ || (255<sqlcipher_sqlite3Strlen30(zFunctionName))
){
return SQLITE_MISUSE_BKPT;
}
@@ -168553,22 +177928,33 @@ SQLITE_PRIVATE int sqlcipher_sqlite3CreateFunc(
** If SQLITE_ANY is specified, add three versions of the function
** to the hash table.
*/
- if( enc==SQLITE_UTF16 ){
- enc = SQLITE_UTF16NATIVE;
- }else if( enc==SQLITE_ANY ){
- int rc;
- rc = sqlcipher_sqlite3CreateFunc(db, zFunctionName, nArg,
- (SQLITE_UTF8|extraFlags)^SQLITE_FUNC_UNSAFE,
- pUserData, xSFunc, xStep, xFinal, xValue, xInverse, pDestructor);
- if( rc==SQLITE_OK ){
+ switch( enc ){
+ case SQLITE_UTF16:
+ enc = SQLITE_UTF16NATIVE;
+ break;
+ case SQLITE_ANY: {
+ int rc;
rc = sqlcipher_sqlite3CreateFunc(db, zFunctionName, nArg,
- (SQLITE_UTF16LE|extraFlags)^SQLITE_FUNC_UNSAFE,
+ (SQLITE_UTF8|extraFlags)^SQLITE_FUNC_UNSAFE,
pUserData, xSFunc, xStep, xFinal, xValue, xInverse, pDestructor);
+ if( rc==SQLITE_OK ){
+ rc = sqlcipher_sqlite3CreateFunc(db, zFunctionName, nArg,
+ (SQLITE_UTF16LE|extraFlags)^SQLITE_FUNC_UNSAFE,
+ pUserData, xSFunc, xStep, xFinal, xValue, xInverse, pDestructor);
+ }
+ if( rc!=SQLITE_OK ){
+ return rc;
+ }
+ enc = SQLITE_UTF16BE;
+ break;
}
- if( rc!=SQLITE_OK ){
- return rc;
- }
- enc = SQLITE_UTF16BE;
+ case SQLITE_UTF8:
+ case SQLITE_UTF16LE:
+ case SQLITE_UTF16BE:
+ break;
+ default:
+ enc = SQLITE_UTF8;
+ break;
}
#else
enc = SQLITE_UTF8;
@@ -168589,6 +177975,10 @@ SQLITE_PRIVATE int sqlcipher_sqlite3CreateFunc(
}else{
sqlcipher_sqlite3ExpirePreparedStatements(db, 0);
}
+ }else if( xSFunc==0 && xFinal==0 ){
+ /* Trying to delete a function that does not exist. This is a no-op.
+ ** https://sqlite.org/forum/forumpost/726219164b */
+ return SQLITE_OK;
}
p = sqlcipher_sqlite3FindFunction(db, zFunctionName, nArg, (u8)enc, 1);
@@ -168661,7 +178051,7 @@ static int createFunctionApi(
xSFunc, xStep, xFinal, xValue, xInverse, pArg
);
if( pArg && pArg->nRef==0 ){
- assert( rc!=SQLITE_OK );
+ assert( rc!=SQLITE_OK || (xStep==0 && xFinal==0) );
xDestroy(p);
sqlcipher_sqlite3_free(pArg);
}
@@ -168987,6 +178377,34 @@ SQLITE_API void *sqlcipher_sqlite3_preupdate_hook(
}
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
+/*
+** Register a function to be invoked prior to each autovacuum that
+** determines the number of pages to vacuum.
+*/
+SQLITE_API int sqlcipher_sqlite3_autovacuum_pages(
+ sqlcipher_sqlite3 *db, /* Attach the hook to this database */
+ unsigned int (*xCallback)(void*,const char*,u32,u32,u32),
+ void *pArg, /* Argument to the function */
+ void (*xDestructor)(void*) /* Destructor for pArg */
+){
+#ifdef SQLITE_ENABLE_API_ARMOR
+ if( !sqlcipher_sqlite3SafetyCheckOk(db) ){
+ if( xDestructor ) xDestructor(pArg);
+ return SQLITE_MISUSE_BKPT;
+ }
+#endif
+ sqlcipher_sqlite3_mutex_enter(db->mutex);
+ if( db->xAutovacDestr ){
+ db->xAutovacDestr(db->pAutovacPagesArg);
+ }
+ db->xAutovacPages = xCallback;
+ db->pAutovacPagesArg = pArg;
+ db->xAutovacDestr = xDestructor;
+ sqlcipher_sqlite3_mutex_leave(db->mutex);
+ return SQLITE_OK;
+}
+
+
#ifndef SQLITE_OMIT_WAL
/*
** The sqlcipher_sqlite3_wal_hook() callback registered by sqlcipher_sqlite3_wal_autocheckpoint().
@@ -169079,7 +178497,7 @@ SQLITE_API int sqlcipher_sqlite3_wal_checkpoint_v2(
return SQLITE_OK;
#else
int rc; /* Return code */
- int iDb = SQLITE_MAX_ATTACHED; /* sqlcipher_sqlite3.aDb[] index of db to checkpoint */
+ int iDb; /* Schema to checkpoint */
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlcipher_sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
@@ -169102,6 +178520,8 @@ SQLITE_API int sqlcipher_sqlite3_wal_checkpoint_v2(
sqlcipher_sqlite3_mutex_enter(db->mutex);
if( zDb && zDb[0] ){
iDb = sqlcipher_sqlite3FindDbName(db, zDb);
+ }else{
+ iDb = SQLITE_MAX_DB; /* This means process all schemas */
}
if( iDb<0 ){
rc = SQLITE_ERROR;
@@ -169150,7 +178570,7 @@ SQLITE_API int sqlcipher_sqlite3_wal_checkpoint(sqlcipher_sqlite3 *db, const cha
** associated with the specific b-tree being checkpointed is taken by
** this function while the checkpoint is running.
**
-** If iDb is passed SQLITE_MAX_ATTACHED, then all attached databases are
+** If iDb is passed SQLITE_MAX_DB then all attached databases are
** checkpointed. If an error is encountered it is returned immediately -
** no attempt is made to checkpoint any remaining databases.
**
@@ -169165,9 +178585,11 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Checkpoint(sqlcipher_sqlite3 *db, int iDb, i
assert( sqlcipher_sqlite3_mutex_held(db->mutex) );
assert( !pnLog || *pnLog==-1 );
assert( !pnCkpt || *pnCkpt==-1 );
+ testcase( iDb==SQLITE_MAX_ATTACHED ); /* See forum post a006d86f72 */
+ testcase( iDb==SQLITE_MAX_DB );
for(i=0; i<db->nDb && rc==SQLITE_OK; i++){
- if( i==iDb || iDb==SQLITE_MAX_ATTACHED ){
+ if( i==iDb || iDb==SQLITE_MAX_DB ){
rc = sqlcipher_sqlite3BtreeCheckpoint(db->aDb[i].pBt, eMode, pnLog, pnCkpt);
pnLog = 0;
pnCkpt = 0;
@@ -169245,6 +178667,19 @@ SQLITE_API const char *sqlcipher_sqlite3_errmsg(sqlcipher_sqlite3 *db){
return z;
}
+/*
+** Return the byte offset of the most recent error
+*/
+SQLITE_API int sqlcipher_sqlite3_error_offset(sqlcipher_sqlite3 *db){
+ int iOffset = -1;
+ if( db && sqlcipher_sqlite3SafetyCheckSickOrOk(db) && db->errCode ){
+ sqlcipher_sqlite3_mutex_enter(db->mutex);
+ iOffset = db->errByteOffset;
+ sqlcipher_sqlite3_mutex_leave(db->mutex);
+ }
+ return iOffset;
+}
+
#ifndef SQLITE_OMIT_UTF16
/*
** Return UTF-16 encoded English language explanation of the most recent
@@ -169505,6 +178940,8 @@ SQLITE_API int sqlcipher_sqlite3_limit(sqlcipher_sqlite3 *db, int limitId, int n
if( newLimit>=0 ){ /* IMP: R-52476-28732 */
if( newLimit>aHardLimit[limitId] ){
newLimit = aHardLimit[limitId]; /* IMP: R-51463-25634 */
+ }else if( newLimit<1 && limitId==SQLITE_LIMIT_LENGTH ){
+ newLimit = 1;
}
db->aLimit[limitId] = newLimit;
}
@@ -169776,7 +179213,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3ParseUri(
*/
static const char *uriParameter(const char *zFilename, const char *zParam){
zFilename += sqlcipher_sqlite3Strlen30(zFilename) + 1;
- while( zFilename[0] ){
+ while( ALWAYS(zFilename!=0) && zFilename[0] ){
int x = strcmp(zFilename, zParam);
zFilename += sqlcipher_sqlite3Strlen30(zFilename) + 1;
if( x==0 ) return zFilename;
@@ -169873,8 +179310,8 @@ static int openDatabase(
** dealt with in the previous code block. Besides these, the only
** valid input flags for sqlcipher_sqlite3_open_v2() are SQLITE_OPEN_READONLY,
** SQLITE_OPEN_READWRITE, SQLITE_OPEN_CREATE, SQLITE_OPEN_SHAREDCACHE,
- ** SQLITE_OPEN_PRIVATECACHE, and some reserved bits. Silently mask
- ** off all other flags.
+ ** SQLITE_OPEN_PRIVATECACHE, SQLITE_OPEN_EXRESCODE, and some reserved
+ ** bits. Silently mask off all other flags.
*/
flags &= ~( SQLITE_OPEN_DELETEONCLOSE |
SQLITE_OPEN_EXCLUSIVE |
@@ -169909,9 +179346,9 @@ static int openDatabase(
}
}
sqlcipher_sqlite3_mutex_enter(db->mutex);
- db->errMask = 0xff;
+ db->errMask = (flags & SQLITE_OPEN_EXRESCODE)!=0 ? 0xffffffff : 0xff;
db->nDb = 2;
- db->magic = SQLITE_MAGIC_BUSY;
+ db->eOpenState = SQLITE_STATE_BUSY;
db->aDb = db->aDbStatic;
db->lookaside.bDisable = 1;
db->lookaside.sz = 0;
@@ -169923,7 +179360,15 @@ static int openDatabase(
db->nextAutovac = -1;
db->szMmap = sqlcipher_sqlite3GlobalConfig.szMmap;
db->nextPagesize = 0;
+ db->init.azInit = sqlcipher_sqlite3StdType; /* Any array of string ptrs will do */
+#ifdef SQLITE_ENABLE_SORTER_MMAP
+ /* Beginning with version 3.37.0, using the VFS xFetch() API to memory-map
+ ** the temporary files used to do external sorts (see code in vdbesort.c)
+ ** is disabled. It can still be used either by defining
+ ** SQLITE_ENABLE_SORTER_MMAP at compile time or by using the
+ ** SQLITE_TESTCTRL_SORTER_MMAP test-control at runtime. */
db->nMaxSorterMmap = 0x7FFFFFFF;
+#endif
db->flags |= SQLITE_ShortColNames
| SQLITE_EnableTrigger
| SQLITE_EnableView
@@ -170071,7 +179516,7 @@ static int openDatabase(
db->aDb[1].zDbSName = "temp";
db->aDb[1].safety_level = PAGER_SYNCHRONOUS_OFF;
- db->magic = SQLITE_MAGIC_OPEN;
+ db->eOpenState = SQLITE_STATE_OPEN;
if( db->mallocFailed ){
goto opendb_out;
}
@@ -170140,12 +179585,12 @@ opendb_out:
sqlcipher_sqlite3_mutex_leave(db->mutex);
}
rc = sqlcipher_sqlite3_errcode(db);
- assert( db!=0 || rc==SQLITE_NOMEM );
- if( rc==SQLITE_NOMEM ){
+ assert( db!=0 || (rc&0xff)==SQLITE_NOMEM );
+ if( (rc&0xff)==SQLITE_NOMEM ){
sqlcipher_sqlite3_close(db);
db = 0;
}else if( rc!=SQLITE_OK ){
- db->magic = SQLITE_MAGIC_SICK;
+ db->eOpenState = SQLITE_STATE_SICK;
}
*ppDb = db;
#ifdef SQLITE_ENABLE_SQLLOG
@@ -170161,7 +179606,7 @@ opendb_out:
#endif
/* END SQLCIPHER */
sqlcipher_sqlite3_free_filename(zOpen);
- return rc & 0xff;
+ return rc;
}
@@ -170461,7 +179906,7 @@ SQLITE_API int sqlcipher_sqlite3_table_column_metadata(
/* Locate the table in question */
pTab = sqlcipher_sqlite3FindTable(db, zTableName, zDbName);
- if( !pTab || pTab->pSelect ){
+ if( !pTab || IsView(pTab) ){
pTab = 0;
goto error_out;
}
@@ -170472,7 +179917,7 @@ SQLITE_API int sqlcipher_sqlite3_table_column_metadata(
}else{
for(iCol=0; iCol<pTab->nCol; iCol++){
pCol = &pTab->aCol[iCol];
- if( 0==sqlcipher_sqlite3StrICmp(pCol->zName, zColumnName) ){
+ if( 0==sqlcipher_sqlite3StrICmp(pCol->zCnName, zColumnName) ){
break;
}
}
@@ -170499,7 +179944,7 @@ SQLITE_API int sqlcipher_sqlite3_table_column_metadata(
*/
if( pCol ){
zDataType = sqlcipher_sqlite3ColumnType(pCol,0);
- zCollSeq = pCol->zColl;
+ zCollSeq = sqlcipher_sqlite3ColumnColl(pCol);
notnull = pCol->notNull!=0;
primarykey = (pCol->colFlags & COLFLAG_PRIMKEY)!=0;
autoinc = pTab->iPKey==iCol && (pTab->tabFlags & TF_Autoincrement)!=0;
@@ -170706,12 +180151,16 @@ SQLITE_API int sqlcipher_sqlite3_test_control(int op, ...){
** sqlcipher_sqlite3_test_control().
*/
case SQLITE_TESTCTRL_FAULT_INSTALL: {
- /* MSVC is picky about pulling func ptrs from va lists.
- ** http://support.microsoft.com/kb/47961
+ /* A bug in MSVC prevents it from understanding pointers to functions
+ ** types in the second argument to va_arg(). Work around the problem
+ ** using a typedef.
+ ** http://support.microsoft.com/kb/47961 <-- dead hyperlink
+ ** Search at http://web.archive.org/ to find the 2015-03-16 archive
+ ** of the link above to see the original text.
** sqlcipher_sqlite3GlobalConfig.xTestCallback = va_arg(ap, int(*)(int));
*/
- typedef int(*TESTCALLBACKFUNC_t)(int);
- sqlcipher_sqlite3GlobalConfig.xTestCallback = va_arg(ap, TESTCALLBACKFUNC_t);
+ typedef int(*sqlcipher_sqlite3FaultFuncType)(int);
+ sqlcipher_sqlite3GlobalConfig.xTestCallback = va_arg(ap, sqlcipher_sqlite3FaultFuncType);
rc = sqlcipher_sqlite3FaultSim(0);
break;
}
@@ -170770,6 +180219,28 @@ SQLITE_API int sqlcipher_sqlite3_test_control(int op, ...){
volatile int x = 0;
assert( /*side-effects-ok*/ (x = va_arg(ap,int))!=0 );
rc = x;
+#if defined(SQLITE_DEBUG)
+ /* Invoke these debugging routines so that the compiler does not
+ ** issue "defined but not used" warnings. */
+ if( x==9999 ){
+ sqlcipher_sqlite3ShowExpr(0);
+ sqlcipher_sqlite3ShowExpr(0);
+ sqlcipher_sqlite3ShowExprList(0);
+ sqlcipher_sqlite3ShowIdList(0);
+ sqlcipher_sqlite3ShowSrcList(0);
+ sqlcipher_sqlite3ShowWith(0);
+ sqlcipher_sqlite3ShowUpsert(0);
+ sqlcipher_sqlite3ShowTriggerStep(0);
+ sqlcipher_sqlite3ShowTriggerStepList(0);
+ sqlcipher_sqlite3ShowTrigger(0);
+ sqlcipher_sqlite3ShowTriggerList(0);
+#ifndef SQLITE_OMIT_WINDOWFUNC
+ sqlcipher_sqlite3ShowWindow(0);
+ sqlcipher_sqlite3ShowWinFunc(0);
+#endif
+ sqlcipher_sqlite3ShowSelect(0);
+ }
+#endif
break;
}
@@ -170834,17 +180305,31 @@ SQLITE_API int sqlcipher_sqlite3_test_control(int op, ...){
*/
case SQLITE_TESTCTRL_OPTIMIZATIONS: {
sqlcipher_sqlite3 *db = va_arg(ap, sqlcipher_sqlite3*);
- db->dbOptFlags = (u16)(va_arg(ap, int) & 0xffff);
+ db->dbOptFlags = va_arg(ap, u32);
break;
}
- /* sqlcipher_sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, int onoff);
+ /* sqlcipher_sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, onoff, xAlt);
**
- ** If parameter onoff is non-zero, subsequent calls to localtime()
- ** and its variants fail. If onoff is zero, undo this setting.
+ ** If parameter onoff is 1, subsequent calls to localtime() fail.
+ ** If 2, then invoke xAlt() instead of localtime(). If 0, normal
+ ** processing.
+ **
+ ** xAlt arguments are void pointers, but they really want to be:
+ **
+ ** int xAlt(const time_t*, struct tm*);
+ **
+ ** xAlt should write results in to struct tm object of its 2nd argument
+ ** and return zero on success, or return non-zero on failure.
*/
case SQLITE_TESTCTRL_LOCALTIME_FAULT: {
sqlcipher_sqlite3GlobalConfig.bLocaltimeFault = va_arg(ap, int);
+ if( sqlcipher_sqlite3GlobalConfig.bLocaltimeFault==2 ){
+ typedef int(*sqlcipher_sqlite3LocaltimeType)(const void*,void*);
+ sqlcipher_sqlite3GlobalConfig.xAltLocaltime = va_arg(ap, sqlcipher_sqlite3LocaltimeType);
+ }else{
+ sqlcipher_sqlite3GlobalConfig.xAltLocaltime = 0;
+ }
break;
}
@@ -170949,12 +180434,16 @@ SQLITE_API int sqlcipher_sqlite3_test_control(int op, ...){
*/
case SQLITE_TESTCTRL_IMPOSTER: {
sqlcipher_sqlite3 *db = va_arg(ap, sqlcipher_sqlite3*);
+ int iDb;
sqlcipher_sqlite3_mutex_enter(db->mutex);
- db->init.iDb = sqlcipher_sqlite3FindDbName(db, va_arg(ap,const char*));
- db->init.busy = db->init.imposterTable = va_arg(ap,int);
- db->init.newTnum = va_arg(ap,int);
- if( db->init.busy==0 && db->init.newTnum>0 ){
- sqlcipher_sqlite3ResetAllSchemasOfConnection(db);
+ iDb = sqlcipher_sqlite3FindDbName(db, va_arg(ap,const char*));
+ if( iDb>=0 ){
+ db->init.iDb = iDb;
+ db->init.busy = db->init.imposterTable = va_arg(ap,int);
+ db->init.newTnum = va_arg(ap,int);
+ if( db->init.busy==0 && db->init.newTnum>0 ){
+ sqlcipher_sqlite3ResetAllSchemasOfConnection(db);
+ }
}
sqlcipher_sqlite3_mutex_leave(db->mutex);
break;
@@ -171009,7 +180498,78 @@ SQLITE_API int sqlcipher_sqlite3_test_control(int op, ...){
break;
}
+ /* sqlcipher_sqlite3_test_control(SQLITE_TESTCTRL_TRACEFLAGS, op, ptr)
+ **
+ ** "ptr" is a pointer to a u32.
+ **
+ ** op==0 Store the current sqlcipher_sqlite3TreeTrace in *ptr
+ ** op==1 Set sqlcipher_sqlite3TreeTrace to the value *ptr
+ ** op==3 Store the current sqlcipher_sqlite3WhereTrace in *ptr
+ ** op==3 Set sqlcipher_sqlite3WhereTrace to the value *ptr
+ */
+ case SQLITE_TESTCTRL_TRACEFLAGS: {
+ int opTrace = va_arg(ap, int);
+ u32 *ptr = va_arg(ap, u32*);
+ switch( opTrace ){
+ case 0: *ptr = sqlcipher_sqlite3TreeTrace; break;
+ case 1: sqlcipher_sqlite3TreeTrace = *ptr; break;
+ case 2: *ptr = sqlcipher_sqlite3WhereTrace; break;
+ case 3: sqlcipher_sqlite3WhereTrace = *ptr; break;
+ }
+ break;
+ }
+ /* sqlcipher_sqlite3_test_control(SQLITE_TESTCTRL_LOGEST,
+ ** double fIn, // Input value
+ ** int *pLogEst, // sqlcipher_sqlite3LogEstFromDouble(fIn)
+ ** u64 *pInt, // sqlcipher_sqlite3LogEstToInt(*pLogEst)
+ ** int *pLogEst2 // sqlcipher_sqlite3LogEst(*pInt)
+ ** );
+ **
+ ** Test access for the LogEst conversion routines.
+ */
+ case SQLITE_TESTCTRL_LOGEST: {
+ double rIn = va_arg(ap, double);
+ LogEst rLogEst = sqlcipher_sqlite3LogEstFromDouble(rIn);
+ int *pI1 = va_arg(ap,int*);
+ u64 *pU64 = va_arg(ap,u64*);
+ int *pI2 = va_arg(ap,int*);
+ *pI1 = rLogEst;
+ *pU64 = sqlcipher_sqlite3LogEstToInt(rLogEst);
+ *pI2 = sqlcipher_sqlite3LogEst(*pU64);
+ break;
+ }
+
+
+#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_WSD)
+ /* sqlcipher_sqlite3_test_control(SQLITE_TESTCTRL_TUNE, id, *piValue)
+ **
+ ** If "id" is an integer between 1 and SQLITE_NTUNE then set the value
+ ** of the id-th tuning parameter to *piValue. If "id" is between -1
+ ** and -SQLITE_NTUNE, then write the current value of the (-id)-th
+ ** tuning parameter into *piValue.
+ **
+ ** Tuning parameters are for use during transient development builds,
+ ** to help find the best values for constants in the query planner.
+ ** Access tuning parameters using the Tuning(ID) macro. Set the
+ ** parameters in the CLI using ".testctrl tune ID VALUE".
+ **
+ ** Transient use only. Tuning parameters should not be used in
+ ** checked-in code.
+ */
+ case SQLITE_TESTCTRL_TUNE: {
+ int id = va_arg(ap, int);
+ int *piValue = va_arg(ap, int*);
+ if( id>0 && id<=SQLITE_NTUNE ){
+ Tuning(id) = *piValue;
+ }else if( id<0 && id>=-SQLITE_NTUNE ){
+ *piValue = Tuning(-id);
+ }else{
+ rc = SQLITE_NOTFOUND;
+ }
+ break;
+ }
+#endif
}
va_end(ap);
#endif /* SQLITE_UNTESTABLE */
@@ -171117,7 +180677,7 @@ SQLITE_API const char *sqlcipher_sqlite3_uri_key(const char *zFilename, int N){
if( zFilename==0 || N<0 ) return 0;
zFilename = databaseName(zFilename);
zFilename += sqlcipher_sqlite3Strlen30(zFilename) + 1;
- while( zFilename[0] && (N--)>0 ){
+ while( ALWAYS(zFilename) && zFilename[0] && (N--)>0 ){
zFilename += sqlcipher_sqlite3Strlen30(zFilename) + 1;
zFilename += sqlcipher_sqlite3Strlen30(zFilename) + 1;
}
@@ -171160,12 +180720,14 @@ SQLITE_API sqlcipher_sqlite3_int64 sqlcipher_sqlite3_uri_int64(
** corruption.
*/
SQLITE_API const char *sqlcipher_sqlite3_filename_database(const char *zFilename){
+ if( zFilename==0 ) return 0;
return databaseName(zFilename);
}
SQLITE_API const char *sqlcipher_sqlite3_filename_journal(const char *zFilename){
+ if( zFilename==0 ) return 0;
zFilename = databaseName(zFilename);
zFilename += sqlcipher_sqlite3Strlen30(zFilename) + 1;
- while( zFilename[0] ){
+ while( ALWAYS(zFilename) && zFilename[0] ){
zFilename += sqlcipher_sqlite3Strlen30(zFilename) + 1;
zFilename += sqlcipher_sqlite3Strlen30(zFilename) + 1;
}
@@ -171176,7 +180738,7 @@ SQLITE_API const char *sqlcipher_sqlite3_filename_wal(const char *zFilename){
return 0;
#else
zFilename = sqlcipher_sqlite3_filename_journal(zFilename);
- zFilename += sqlcipher_sqlite3Strlen30(zFilename) + 1;
+ if( zFilename ) zFilename += sqlcipher_sqlite3Strlen30(zFilename) + 1;
return zFilename;
#endif
}
@@ -171190,6 +180752,24 @@ SQLITE_PRIVATE Btree *sqlcipher_sqlite3DbNameToBtree(sqlcipher_sqlite3 *db, cons
}
/*
+** Return the name of the N-th database schema. Return NULL if N is out
+** of range.
+*/
+SQLITE_API const char *sqlcipher_sqlite3_db_name(sqlcipher_sqlite3 *db, int N){
+#ifdef SQLITE_ENABLE_API_ARMOR
+ if( !sqlcipher_sqlite3SafetyCheckOk(db) ){
+ (void)SQLITE_MISUSE_BKPT;
+ return 0;
+ }
+#endif
+ if( N<0 || N>=db->nDb ){
+ return 0;
+ }else{
+ return db->aDb[N].zDbSName;
+ }
+}
+
+/*
** Return the filename of the database associated with a database
** connection.
*/
@@ -172452,7 +182032,7 @@ SQLITE_PRIVATE Fts3HashElem *sqlcipher_sqlite3Fts3HashFindElem(const Fts3Hash *,
** is used for assert() conditions that are true only if it can be
** guranteed that the database is not corrupt.
*/
-#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
+#ifdef SQLITE_DEBUG
SQLITE_API extern int sqlcipher_sqlite3_fts3_may_be_corrupt;
# define assert_fts3_nc(x) assert(sqlcipher_sqlite3_fts3_may_be_corrupt || (x))
#else
@@ -172469,17 +182049,18 @@ SQLITE_API extern int sqlcipher_sqlite3_fts3_may_be_corrupt;
** Macros indicating that conditional expressions are always true or
** false.
*/
-#ifdef SQLITE_COVERAGE_TEST
-# define ALWAYS(x) (1)
-# define NEVER(X) (0)
-#elif defined(SQLITE_DEBUG)
-# define ALWAYS(x) sqlcipher_sqlite3Fts3Always((x)!=0)
-# define NEVER(x) sqlcipher_sqlite3Fts3Never((x)!=0)
-SQLITE_PRIVATE int sqlcipher_sqlite3Fts3Always(int b);
-SQLITE_PRIVATE int sqlcipher_sqlite3Fts3Never(int b);
+#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
+# define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1
+#endif
+#if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS)
+# 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)
+# define ALWAYS(X) (X)
+# define NEVER(X) (X)
#endif
/*
@@ -172875,7 +182456,7 @@ struct Fts3MultiSegReader {
int nAdvance; /* How many seg-readers to advance */
Fts3SegFilter *pFilter; /* Pointer to filter object */
char *aBuffer; /* Buffer to merge doclists in */
- int nBuffer; /* Allocated size of aBuffer[] in bytes */
+ i64 nBuffer; /* Allocated size of aBuffer[] in bytes */
int iColFilter; /* If >=0, filter for this column */
int bRestart;
@@ -172938,6 +182519,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Fts3ExprFree(Fts3Expr *);
SQLITE_PRIVATE int sqlcipher_sqlite3Fts3ExprInitTestInterface(sqlcipher_sqlite3 *db, Fts3Hash*);
SQLITE_PRIVATE int sqlcipher_sqlite3Fts3InitTerm(sqlcipher_sqlite3 *db);
#endif
+SQLITE_PRIVATE void *sqlcipher_sqlite3Fts3MallocZero(i64 nByte);
SQLITE_PRIVATE int sqlcipher_sqlite3Fts3OpenTokenizer(sqlcipher_sqlite3_tokenizer *, int, const char *, int,
sqlcipher_sqlite3_tokenizer_cursor **
@@ -172957,7 +182539,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Fts3MsrOvfl(Fts3Cursor *, Fts3MultiSegReader
SQLITE_PRIVATE int sqlcipher_sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr);
/* fts3_tokenize_vtab.c */
-SQLITE_PRIVATE int sqlcipher_sqlite3Fts3InitTok(sqlcipher_sqlite3*, Fts3Hash *);
+SQLITE_PRIVATE int sqlcipher_sqlite3Fts3InitTok(sqlcipher_sqlite3*, Fts3Hash *, void(*xDestroy)(void*));
/* fts3_unicode2.c (functions generated by parsing unicode text files) */
#ifndef SQLITE_DISABLE_FTS3_UNICODE
@@ -172990,25 +182572,26 @@ SQLITE_PRIVATE int sqlcipher_sqlite3FtsUnicodeIsdiacritic(int);
SQLITE_EXTENSION_INIT1
#endif
+typedef struct Fts3HashWrapper Fts3HashWrapper;
+struct Fts3HashWrapper {
+ Fts3Hash hash; /* Hash table */
+ int nRef; /* Number of pointers to this object */
+};
+
static int fts3EvalNext(Fts3Cursor *pCsr);
static int fts3EvalStart(Fts3Cursor *pCsr);
static int fts3TermSegReaderCursor(
Fts3Cursor *, const char *, int, int, Fts3MultiSegReader **);
-#ifndef SQLITE_AMALGAMATION
-# if defined(SQLITE_DEBUG)
-SQLITE_PRIVATE int sqlcipher_sqlite3Fts3Always(int b) { assert( b ); return b; }
-SQLITE_PRIVATE int sqlcipher_sqlite3Fts3Never(int b) { assert( !b ); return b; }
-# endif
-#endif
-
/*
** This variable is set to false when running tests for which the on disk
** structures should not be corrupt. Otherwise, true. If it is false, extra
** assert() conditions in the fts3 code are activated - conditions that are
** only true if it is guaranteed that the fts3 database is not corrupt.
*/
+#ifdef SQLITE_DEBUG
SQLITE_API int sqlcipher_sqlite3_fts3_may_be_corrupt = 1;
+#endif
/*
** Write a 64-bit variable-length integer to memory starting at p[0].
@@ -173859,7 +183442,7 @@ static int fts3InitVtab(
sqlcipher_sqlite3_vtab **ppVTab, /* Write the resulting vtab structure here */
char **pzErr /* Write any error message here */
){
- Fts3Hash *pHash = (Fts3Hash *)pAux;
+ Fts3Hash *pHash = &((Fts3HashWrapper*)pAux)->hash;
Fts3Table *p = 0; /* Pointer to allocated vtab */
int rc = SQLITE_OK; /* Return code */
int i; /* Iterator variable */
@@ -174579,7 +184162,7 @@ static int fts3ScanInteriorNode(
char *zBuffer = 0; /* Buffer to load terms into */
i64 nAlloc = 0; /* Size of allocated buffer */
int isFirstTerm = 1; /* True when processing first term on page */
- sqlcipher_sqlite3_int64 iChild; /* Block id of child node to descend to */
+ u64 iChild; /* Block id of child node to descend to */
int nBuffer = 0; /* Total term size */
/* Skip over the 'height' varint that occurs at the start of every
@@ -174595,8 +184178,8 @@ static int fts3ScanInteriorNode(
** table, then there are always 20 bytes of zeroed padding following the
** nNode bytes of content (see sqlcipher_sqlite3Fts3ReadBlock() for details).
*/
- zCsr += sqlcipher_sqlite3Fts3GetVarint(zCsr, &iChild);
- zCsr += sqlcipher_sqlite3Fts3GetVarint(zCsr, &iChild);
+ zCsr += sqlcipher_sqlite3Fts3GetVarintU(zCsr, &iChild);
+ zCsr += sqlcipher_sqlite3Fts3GetVarintU(zCsr, &iChild);
if( zCsr>zEnd ){
return FTS_CORRUPT_VTAB;
}
@@ -174649,20 +184232,20 @@ static int fts3ScanInteriorNode(
*/
cmp = memcmp(zTerm, zBuffer, (nBuffer>nTerm ? nTerm : nBuffer));
if( piFirst && (cmp<0 || (cmp==0 && nBuffer>nTerm)) ){
- *piFirst = iChild;
+ *piFirst = (i64)iChild;
piFirst = 0;
}
if( piLast && cmp<0 ){
- *piLast = iChild;
+ *piLast = (i64)iChild;
piLast = 0;
}
iChild++;
};
- if( piFirst ) *piFirst = iChild;
- if( piLast ) *piLast = iChild;
+ if( piFirst ) *piFirst = (i64)iChild;
+ if( piLast ) *piLast = (i64)iChild;
finish_scan:
sqlcipher_sqlite3_free(zBuffer);
@@ -175569,7 +185152,7 @@ static int fts3TermSelectMerge(
**
** Similar padding is added in the fts3DoclistOrMerge() function.
*/
- pTS->aaOutput[0] = sqlcipher_sqlite3_malloc(nDoclist + FTS3_VARINT_MAX + 1);
+ pTS->aaOutput[0] = sqlcipher_sqlite3_malloc64((i64)nDoclist + FTS3_VARINT_MAX + 1);
pTS->anOutput[0] = nDoclist;
if( pTS->aaOutput[0] ){
memcpy(pTS->aaOutput[0], aDoclist, nDoclist);
@@ -176268,14 +185851,20 @@ static int fts3SetHasStat(Fts3Table *p){
*/
static int fts3BeginMethod(sqlcipher_sqlite3_vtab *pVtab){
Fts3Table *p = (Fts3Table*)pVtab;
+ int rc;
UNUSED_PARAMETER(pVtab);
assert( p->pSegments==0 );
assert( p->nPendingData==0 );
assert( p->inTransaction!=1 );
- TESTONLY( p->inTransaction = 1 );
- TESTONLY( p->mxSavepoint = -1; );
p->nLeafAdd = 0;
- return fts3SetHasStat(p);
+ rc = fts3SetHasStat(p);
+#ifdef SQLITE_DEBUG
+ if( rc==SQLITE_OK ){
+ p->inTransaction = 1;
+ p->mxSavepoint = -1;
+ }
+#endif
+ return rc;
}
/*
@@ -176688,9 +186277,12 @@ static const sqlcipher_sqlite3_module fts3Module = {
** allocated for the tokenizer hash table.
*/
static void hashDestroy(void *p){
- Fts3Hash *pHash = (Fts3Hash *)p;
- sqlcipher_sqlite3Fts3HashClear(pHash);
- sqlcipher_sqlite3_free(pHash);
+ Fts3HashWrapper *pHash = (Fts3HashWrapper *)p;
+ pHash->nRef--;
+ if( pHash->nRef<=0 ){
+ sqlcipher_sqlite3Fts3HashClear(&pHash->hash);
+ sqlcipher_sqlite3_free(pHash);
+ }
}
/*
@@ -176720,7 +186312,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Fts3IcuTokenizerModule(sqlcipher_sqlite3_to
*/
SQLITE_PRIVATE int sqlcipher_sqlite3Fts3Init(sqlcipher_sqlite3 *db){
int rc = SQLITE_OK;
- Fts3Hash *pHash = 0;
+ Fts3HashWrapper *pHash = 0;
const sqlcipher_sqlite3_tokenizer_module *pSimple = 0;
const sqlcipher_sqlite3_tokenizer_module *pPorter = 0;
#ifndef SQLITE_DISABLE_FTS3_UNICODE
@@ -176748,23 +186340,24 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Fts3Init(sqlcipher_sqlite3 *db){
sqlcipher_sqlite3Fts3PorterTokenizerModule(&pPorter);
/* Allocate and initialize the hash-table used to store tokenizers. */
- pHash = sqlcipher_sqlite3_malloc(sizeof(Fts3Hash));
+ pHash = sqlcipher_sqlite3_malloc(sizeof(Fts3HashWrapper));
if( !pHash ){
rc = SQLITE_NOMEM;
}else{
- sqlcipher_sqlite3Fts3HashInit(pHash, FTS3_HASH_STRING, 1);
+ sqlcipher_sqlite3Fts3HashInit(&pHash->hash, FTS3_HASH_STRING, 1);
+ pHash->nRef = 0;
}
/* Load the built-in tokenizers into the hash table */
if( rc==SQLITE_OK ){
- if( sqlcipher_sqlite3Fts3HashInsert(pHash, "simple", 7, (void *)pSimple)
- || sqlcipher_sqlite3Fts3HashInsert(pHash, "porter", 7, (void *)pPorter)
+ if( sqlcipher_sqlite3Fts3HashInsert(&pHash->hash, "simple", 7, (void *)pSimple)
+ || sqlcipher_sqlite3Fts3HashInsert(&pHash->hash, "porter", 7, (void *)pPorter)
#ifndef SQLITE_DISABLE_FTS3_UNICODE
- || sqlcipher_sqlite3Fts3HashInsert(pHash, "unicode61", 10, (void *)pUnicode)
+ || sqlcipher_sqlite3Fts3HashInsert(&pHash->hash, "unicode61", 10, (void *)pUnicode)
#endif
#ifdef SQLITE_ENABLE_ICU
- || (pIcu && sqlcipher_sqlite3Fts3HashInsert(pHash, "icu", 4, (void *)pIcu))
+ || (pIcu && sqlcipher_sqlite3Fts3HashInsert(&pHash->hash, "icu", 4, (void *)pIcu))
#endif
){
rc = SQLITE_NOMEM;
@@ -176773,7 +186366,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Fts3Init(sqlcipher_sqlite3 *db){
#ifdef SQLITE_TEST
if( rc==SQLITE_OK ){
- rc = sqlcipher_sqlite3Fts3ExprInitTestInterface(db, pHash);
+ rc = sqlcipher_sqlite3Fts3ExprInitTestInterface(db, &pHash->hash);
}
#endif
@@ -176782,23 +186375,26 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Fts3Init(sqlcipher_sqlite3 *db){
** module with sqlite.
*/
if( SQLITE_OK==rc
- && SQLITE_OK==(rc = sqlcipher_sqlite3Fts3InitHashTable(db, pHash, "fts3_tokenizer"))
+ && SQLITE_OK==(rc=sqlcipher_sqlite3Fts3InitHashTable(db,&pHash->hash,"fts3_tokenizer"))
&& SQLITE_OK==(rc = sqlcipher_sqlite3_overload_function(db, "snippet", -1))
&& SQLITE_OK==(rc = sqlcipher_sqlite3_overload_function(db, "offsets", 1))
&& SQLITE_OK==(rc = sqlcipher_sqlite3_overload_function(db, "matchinfo", 1))
&& SQLITE_OK==(rc = sqlcipher_sqlite3_overload_function(db, "matchinfo", 2))
&& SQLITE_OK==(rc = sqlcipher_sqlite3_overload_function(db, "optimize", 1))
){
+ pHash->nRef++;
rc = sqlcipher_sqlite3_create_module_v2(
db, "fts3", &fts3Module, (void *)pHash, hashDestroy
);
if( rc==SQLITE_OK ){
+ pHash->nRef++;
rc = sqlcipher_sqlite3_create_module_v2(
- db, "fts4", &fts3Module, (void *)pHash, 0
+ db, "fts4", &fts3Module, (void *)pHash, hashDestroy
);
}
if( rc==SQLITE_OK ){
- rc = sqlcipher_sqlite3Fts3InitTok(db, (void *)pHash);
+ pHash->nRef++;
+ rc = sqlcipher_sqlite3Fts3InitTok(db, (void *)pHash, hashDestroy);
}
return rc;
}
@@ -176807,7 +186403,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Fts3Init(sqlcipher_sqlite3 *db){
/* An error has occurred. Delete the hash table and return the error code. */
assert( rc!=SQLITE_OK );
if( pHash ){
- sqlcipher_sqlite3Fts3HashClear(pHash);
+ sqlcipher_sqlite3Fts3HashClear(&pHash->hash);
sqlcipher_sqlite3_free(pHash);
}
return rc;
@@ -176976,8 +186572,7 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
char *aPoslist = 0; /* Position list for deferred tokens */
int nPoslist = 0; /* Number of bytes in aPoslist */
int iPrev = -1; /* Token number of previous deferred token */
-
- assert( pPhrase->doclist.bFreeList==0 );
+ char *aFree = (pPhrase->doclist.bFreeList ? pPhrase->doclist.pList : 0);
for(iToken=0; iToken<pPhrase->nToken; iToken++){
Fts3PhraseToken *pToken = &pPhrase->aToken[iToken];
@@ -176991,6 +186586,7 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
if( pList==0 ){
sqlcipher_sqlite3_free(aPoslist);
+ sqlcipher_sqlite3_free(aFree);
pPhrase->doclist.pList = 0;
pPhrase->doclist.nList = 0;
return SQLITE_OK;
@@ -177011,6 +186607,7 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
nPoslist = (int)(aOut - aPoslist);
if( nPoslist==0 ){
sqlcipher_sqlite3_free(aPoslist);
+ sqlcipher_sqlite3_free(aFree);
pPhrase->doclist.pList = 0;
pPhrase->doclist.nList = 0;
return SQLITE_OK;
@@ -177043,13 +186640,14 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
nDistance = iPrev - nMaxUndeferred;
}
- aOut = (char *)sqlcipher_sqlite3_malloc(nPoslist+8);
+ aOut = (char *)sqlcipher_sqlite3Fts3MallocZero(nPoslist+FTS3_BUFFER_PADDING);
if( !aOut ){
sqlcipher_sqlite3_free(aPoslist);
return SQLITE_NOMEM;
}
pPhrase->doclist.pList = aOut;
+ assert( p1 && p2 );
if( fts3PoslistPhraseMerge(&aOut, nDistance, 0, 1, &p1, &p2) ){
pPhrase->doclist.bFreeList = 1;
pPhrase->doclist.nList = (int)(aOut - pPhrase->doclist.pList);
@@ -177062,6 +186660,7 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
}
}
+ if( pPhrase->doclist.pList!=aFree ) sqlcipher_sqlite3_free(aFree);
return SQLITE_OK;
}
#endif /* SQLITE_DISABLE_FTS4_DEFERRED */
@@ -177154,7 +186753,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Fts3DoclistPrev(
assert( nDoclist>0 );
assert( *pbEof==0 );
- assert( p || *piDocid==0 );
+ assert_fts3_nc( p || *piDocid==0 );
assert( !p || (p>aDoclist && p<&aDoclist[nDoclist]) );
if( p==0 ){
@@ -177410,7 +187009,7 @@ static int fts3EvalIncrPhraseNext(
if( bEof==0 ){
int nList = 0;
int nByte = a[p->nToken-1].nList;
- char *aDoclist = sqlcipher_sqlite3_malloc(nByte+FTS3_BUFFER_PADDING);
+ char *aDoclist = sqlcipher_sqlite3_malloc64((i64)nByte+FTS3_BUFFER_PADDING);
if( !aDoclist ) return SQLITE_NOMEM;
memcpy(aDoclist, a[p->nToken-1].pList, nByte+1);
memset(&aDoclist[nByte], 0, FTS3_BUFFER_PADDING);
@@ -177804,16 +187403,15 @@ static int fts3EvalStart(Fts3Cursor *pCsr){
#ifndef SQLITE_DISABLE_FTS4_DEFERRED
if( rc==SQLITE_OK && nToken>1 && pTab->bFts4 ){
Fts3TokenAndCost *aTC;
- Fts3Expr **apOr;
aTC = (Fts3TokenAndCost *)sqlcipher_sqlite3_malloc64(
sizeof(Fts3TokenAndCost) * nToken
+ sizeof(Fts3Expr *) * nOr * 2
);
- apOr = (Fts3Expr **)&aTC[nToken];
if( !aTC ){
rc = SQLITE_NOMEM;
}else{
+ Fts3Expr **apOr = (Fts3Expr **)&aTC[nToken];
int ii;
Fts3TokenAndCost *pTC = aTC;
Fts3Expr **ppOr = apOr;
@@ -177894,9 +187492,9 @@ static int fts3EvalNearTrim(
);
if( res ){
nNew = (int)(pOut - pPhrase->doclist.pList) - 1;
- if( nNew>=0 ){
+ assert_fts3_nc( nNew<=pPhrase->doclist.nList && nNew>0 );
+ if( nNew>=0 && nNew<=pPhrase->doclist.nList ){
assert( pPhrase->doclist.pList[nNew]=='\0' );
- assert( nNew<=pPhrase->doclist.nList && nNew>0 );
memset(&pPhrase->doclist.pList[nNew], 0, pPhrase->doclist.nList - nNew);
pPhrase->doclist.nList = nNew;
}
@@ -178019,8 +187617,8 @@ static void fts3EvalNextRow(
Fts3Expr *pRight = pExpr->pRight;
sqlcipher_sqlite3_int64 iCmp = DOCID_CMP(pLeft->iDocid, pRight->iDocid);
- assert( pLeft->bStart || pLeft->iDocid==pRight->iDocid );
- assert( pRight->bStart || pLeft->iDocid==pRight->iDocid );
+ assert_fts3_nc( pLeft->bStart || pLeft->iDocid==pRight->iDocid );
+ assert_fts3_nc( pRight->bStart || pLeft->iDocid==pRight->iDocid );
if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
fts3EvalNextRow(pCsr, pLeft, pRc);
@@ -178237,11 +187835,10 @@ static int fts3EvalTestExpr(
default: {
#ifndef SQLITE_DISABLE_FTS4_DEFERRED
- if( pCsr->pDeferred
- && (pExpr->iDocid==pCsr->iPrevId || pExpr->bDeferred)
- ){
+ if( pCsr->pDeferred && (pExpr->bDeferred || (
+ pExpr->iDocid==pCsr->iPrevId && pExpr->pPhrase->doclist.pList
+ ))){
Fts3Phrase *pPhrase = pExpr->pPhrase;
- assert( pExpr->bDeferred || pPhrase->doclist.bFreeList==0 );
if( pExpr->bDeferred ){
fts3EvalInvalidatePoslist(pPhrase);
}
@@ -178658,6 +188255,9 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Fts3EvalPhrasePoslist(
if( bEofSave==0 && pNear->iDocid==iDocid ) break;
}
assert( rc!=SQLITE_OK || pPhrase->bIncr==0 );
+ if( rc==SQLITE_OK && pNear->bEof!=bEofSave ){
+ rc = FTS_CORRUPT_VTAB;
+ }
}
if( bTreeEof ){
while( rc==SQLITE_OK && !pNear->bEof ){
@@ -179080,6 +188680,7 @@ static int fts3auxNextMethod(sqlcipher_sqlite3_vtab_cursor *pCursor){
if( fts3auxGrowStatArray(pCsr, 2) ) return SQLITE_NOMEM;
memset(pCsr->aStat, 0, sizeof(struct Fts3auxColstats) * pCsr->nStat);
iCol = 0;
+ rc = SQLITE_OK;
while( i<nDoclist ){
sqlcipher_sqlite3_int64 v = 0;
@@ -179123,6 +188724,10 @@ static int fts3auxNextMethod(sqlcipher_sqlite3_vtab_cursor *pCursor){
/* State 3. The integer just read is a column number. */
default: assert( eState==3 );
iCol = (int)v;
+ if( iCol<1 ){
+ rc = SQLITE_CORRUPT_VTAB;
+ break;
+ }
if( fts3auxGrowStatArray(pCsr, iCol+2) ) return SQLITE_NOMEM;
pCsr->aStat[iCol+1].nDoc++;
eState = 2;
@@ -179131,7 +188736,6 @@ static int fts3auxNextMethod(sqlcipher_sqlite3_vtab_cursor *pCursor){
}
pCsr->iCol = 0;
- rc = SQLITE_OK;
}else{
pCsr->isEof = 1;
}
@@ -179189,6 +188793,7 @@ static int fts3auxFilterMethod(
sqlcipher_sqlite3Fts3SegReaderFinish(&pCsr->csr);
sqlcipher_sqlite3_free((void *)pCsr->filter.zTerm);
sqlcipher_sqlite3_free(pCsr->aStat);
+ sqlcipher_sqlite3_free(pCsr->zStop);
memset(&pCsr->csr, 0, ((u8*)&pCsr[1]) - (u8*)&pCsr->csr);
pCsr->filter.flags = FTS3_SEGMENT_REQUIRE_POS|FTS3_SEGMENT_IGNORE_EMPTY;
@@ -179459,7 +189064,7 @@ static int fts3isspace(char c){
** zero the memory before returning a pointer to it. If unsuccessful,
** return NULL.
*/
-static void *fts3MallocZero(sqlcipher_sqlite3_int64 nByte){
+SQLITE_PRIVATE void *sqlcipher_sqlite3Fts3MallocZero(sqlcipher_sqlite3_int64 nByte){
void *pRet = sqlcipher_sqlite3_malloc64(nByte);
if( pRet ) memset(pRet, 0, nByte);
return pRet;
@@ -179540,7 +189145,7 @@ static int getNextToken(
rc = pModule->xNext(pCursor, &zToken, &nToken, &iStart, &iEnd, &iPosition);
if( rc==SQLITE_OK ){
nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase) + nToken;
- pRet = (Fts3Expr *)fts3MallocZero(nByte);
+ pRet = (Fts3Expr *)sqlcipher_sqlite3Fts3MallocZero(nByte);
if( !pRet ){
rc = SQLITE_NOMEM;
}else{
@@ -179795,7 +189400,7 @@ static int getNextNode(
if( fts3isspace(cNext)
|| cNext=='"' || cNext=='(' || cNext==')' || cNext==0
){
- pRet = (Fts3Expr *)fts3MallocZero(sizeof(Fts3Expr));
+ pRet = (Fts3Expr *)sqlcipher_sqlite3Fts3MallocZero(sizeof(Fts3Expr));
if( !pRet ){
return SQLITE_NOMEM;
}
@@ -179830,6 +189435,11 @@ static int getNextNode(
if( *zInput=='(' ){
int nConsumed = 0;
pParse->nNest++;
+#if !defined(SQLITE_MAX_EXPR_DEPTH)
+ if( pParse->nNest>1000 ) return SQLITE_ERROR;
+#elif SQLITE_MAX_EXPR_DEPTH>0
+ if( pParse->nNest>SQLITE_MAX_EXPR_DEPTH ) return SQLITE_ERROR;
+#endif
rc = fts3ExprParse(pParse, zInput+1, nInput-1, ppExpr, &nConsumed);
*pnConsumed = (int)(zInput - z) + 1 + nConsumed;
return rc;
@@ -179969,7 +189579,7 @@ static int fts3ExprParse(
&& p->eType==FTSQUERY_PHRASE && pParse->isNot
){
/* Create an implicit NOT operator. */
- Fts3Expr *pNot = fts3MallocZero(sizeof(Fts3Expr));
+ Fts3Expr *pNot = sqlcipher_sqlite3Fts3MallocZero(sizeof(Fts3Expr));
if( !pNot ){
sqlcipher_sqlite3Fts3ExprFree(p);
rc = SQLITE_NOMEM;
@@ -180003,7 +189613,7 @@ static int fts3ExprParse(
/* Insert an implicit AND operator. */
Fts3Expr *pAnd;
assert( pRet && pPrev );
- pAnd = fts3MallocZero(sizeof(Fts3Expr));
+ pAnd = sqlcipher_sqlite3Fts3MallocZero(sizeof(Fts3Expr));
if( !pAnd ){
sqlcipher_sqlite3Fts3ExprFree(p);
rc = SQLITE_NOMEM;
@@ -181635,7 +191245,7 @@ static int porterNext(
if( n>c->nAllocated ){
char *pNew;
c->nAllocated = n+20;
- pNew = sqlcipher_sqlite3_realloc(c->zToken, c->nAllocated);
+ pNew = sqlcipher_sqlite3_realloc64(c->zToken, c->nAllocated);
if( !pNew ) return SQLITE_NOMEM;
c->zToken = pNew;
}
@@ -182387,7 +191997,7 @@ static int simpleNext(
if( n>c->nTokenAllocated ){
char *pNew;
c->nTokenAllocated = n+20;
- pNew = sqlcipher_sqlite3_realloc(c->pToken, c->nTokenAllocated);
+ pNew = sqlcipher_sqlite3_realloc64(c->pToken, c->nTokenAllocated);
if( !pNew ) return SQLITE_NOMEM;
c->pToken = pNew;
}
@@ -182859,7 +192469,7 @@ static int fts3tokRowidMethod(
** Register the fts3tok module with database connection db. Return SQLITE_OK
** if successful or an error code if sqlcipher_sqlite3_create_module() fails.
*/
-SQLITE_PRIVATE int sqlcipher_sqlite3Fts3InitTok(sqlcipher_sqlite3 *db, Fts3Hash *pHash){
+SQLITE_PRIVATE int sqlcipher_sqlite3Fts3InitTok(sqlcipher_sqlite3 *db, Fts3Hash *pHash, void(*xDestroy)(void*)){
static const sqlcipher_sqlite3_module fts3tok_module = {
0, /* iVersion */
fts3tokConnectMethod, /* xCreate */
@@ -182888,7 +192498,9 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Fts3InitTok(sqlcipher_sqlite3 *db, Fts3Hash
};
int rc; /* Return code */
- rc = sqlcipher_sqlite3_create_module(db, "fts3tokenize", &fts3tok_module, (void*)pHash);
+ rc = sqlcipher_sqlite3_create_module_v2(
+ db, "fts3tokenize", &fts3tok_module, (void*)pHash, xDestroy
+ );
return rc;
}
@@ -183547,7 +193159,7 @@ static int fts3PendingListAppendVarint(
/* Allocate or grow the PendingList as required. */
if( !p ){
- p = sqlcipher_sqlite3_malloc(sizeof(*p) + 100);
+ p = sqlcipher_sqlite3_malloc64(sizeof(*p) + 100);
if( !p ){
return SQLITE_NOMEM;
}
@@ -183556,14 +193168,14 @@ static int fts3PendingListAppendVarint(
p->nData = 0;
}
else if( p->nData+FTS3_VARINT_MAX+1>p->nSpace ){
- int nNew = p->nSpace * 2;
- p = sqlcipher_sqlite3_realloc(p, sizeof(*p) + nNew);
+ i64 nNew = p->nSpace * 2;
+ p = sqlcipher_sqlite3_realloc64(p, sizeof(*p) + nNew);
if( !p ){
sqlcipher_sqlite3_free(*pp);
*pp = 0;
return SQLITE_NOMEM;
}
- p->nSpace = nNew;
+ p->nSpace = (int)nNew;
p->aData = (char *)&p[1];
}
@@ -184120,7 +193732,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Fts3ReadBlock(
int nByte = sqlcipher_sqlite3_blob_bytes(p->pSegments);
*pnBlob = nByte;
if( paBlob ){
- char *aByte = sqlcipher_sqlite3_malloc(nByte + FTS3_NODE_PADDING);
+ char *aByte = sqlcipher_sqlite3_malloc64((i64)nByte + FTS3_NODE_PADDING);
if( !aByte ){
rc = SQLITE_NOMEM;
}else{
@@ -184233,9 +193845,19 @@ static int fts3SegReaderNext(
char *aCopy;
PendingList *pList = (PendingList *)fts3HashData(pElem);
int nCopy = pList->nData+1;
- pReader->zTerm = (char *)fts3HashKey(pElem);
- pReader->nTerm = fts3HashKeysize(pElem);
- aCopy = (char*)sqlcipher_sqlite3_malloc(nCopy);
+
+ int nTerm = fts3HashKeysize(pElem);
+ if( (nTerm+1)>pReader->nTermAlloc ){
+ sqlcipher_sqlite3_free(pReader->zTerm);
+ pReader->zTerm = (char*)sqlcipher_sqlite3_malloc64(((i64)nTerm+1)*2);
+ if( !pReader->zTerm ) return SQLITE_NOMEM;
+ pReader->nTermAlloc = (nTerm+1)*2;
+ }
+ memcpy(pReader->zTerm, fts3HashKey(pElem), nTerm);
+ pReader->zTerm[nTerm] = '\0';
+ pReader->nTerm = nTerm;
+
+ aCopy = (char*)sqlcipher_sqlite3_malloc64(nCopy);
if( !aCopy ) return SQLITE_NOMEM;
memcpy(aCopy, pList->aData, nCopy);
pReader->nNode = pReader->nDoclist = nCopy;
@@ -184487,9 +194109,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Fts3MsrOvfl(
*/
SQLITE_PRIVATE void sqlcipher_sqlite3Fts3SegReaderFree(Fts3SegReader *pReader){
if( pReader ){
- if( !fts3SegReaderIsPending(pReader) ){
- sqlcipher_sqlite3_free(pReader->zTerm);
- }
+ sqlcipher_sqlite3_free(pReader->zTerm);
if( !fts3SegReaderIsRootOnly(pReader) ){
sqlcipher_sqlite3_free(pReader->aNode);
}
@@ -184524,7 +194144,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Fts3SegReaderNew(
nExtra = nRoot + FTS3_NODE_PADDING;
}
- pReader = (Fts3SegReader *)sqlcipher_sqlite3_malloc(sizeof(Fts3SegReader) + nExtra);
+ pReader = (Fts3SegReader *)sqlcipher_sqlite3_malloc64(sizeof(Fts3SegReader) + nExtra);
if( !pReader ){
return SQLITE_NOMEM;
}
@@ -184616,7 +194236,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Fts3SegReaderPending(
if( nElem==nAlloc ){
Fts3HashElem **aElem2;
nAlloc += 16;
- aElem2 = (Fts3HashElem **)sqlcipher_sqlite3_realloc(
+ aElem2 = (Fts3HashElem **)sqlcipher_sqlite3_realloc64(
aElem, nAlloc*sizeof(Fts3HashElem *)
);
if( !aElem2 ){
@@ -184705,7 +194325,7 @@ static int fts3SegReaderCmp(Fts3SegReader *pLhs, Fts3SegReader *pRhs){
if( rc==0 ){
rc = pRhs->iIdx - pLhs->iIdx;
}
- assert( rc!=0 );
+ assert_fts3_nc( rc!=0 );
return rc;
}
@@ -184901,8 +194521,8 @@ static int fts3PrefixCompress(
int nNext /* Size of buffer zNext in bytes */
){
int n;
- UNUSED_PARAMETER(nNext);
- for(n=0; n<nPrev && zPrev[n]==zNext[n]; n++);
+ for(n=0; n<nPrev && n<nNext && zPrev[n]==zNext[n]; n++);
+ assert_fts3_nc( n<nNext );
return n;
}
@@ -184950,7 +194570,7 @@ static int fts3NodeAddTerm(
** this is not expected to be a serious problem.
*/
assert( pTree->aData==(char *)&pTree[1] );
- pTree->aData = (char *)sqlcipher_sqlite3_malloc(nReq);
+ pTree->aData = (char *)sqlcipher_sqlite3_malloc64(nReq);
if( !pTree->aData ){
return SQLITE_NOMEM;
}
@@ -184968,7 +194588,7 @@ static int fts3NodeAddTerm(
if( isCopyTerm ){
if( pTree->nMalloc<nTerm ){
- char *zNew = sqlcipher_sqlite3_realloc(pTree->zMalloc, nTerm*2);
+ char *zNew = sqlcipher_sqlite3_realloc64(pTree->zMalloc, (i64)nTerm*2);
if( !zNew ){
return SQLITE_NOMEM;
}
@@ -184994,7 +194614,7 @@ static int fts3NodeAddTerm(
** now. Instead, the term is inserted into the parent of pTree. If pTree
** has no parent, one is created here.
*/
- pNew = (SegmentNode *)sqlcipher_sqlite3_malloc(sizeof(SegmentNode) + p->nNodeSize);
+ pNew = (SegmentNode *)sqlcipher_sqlite3_malloc64(sizeof(SegmentNode) + p->nNodeSize);
if( !pNew ){
return SQLITE_NOMEM;
}
@@ -185132,7 +194752,7 @@ static int fts3SegWriterAdd(
){
int nPrefix; /* Size of term prefix in bytes */
int nSuffix; /* Size of term suffix in bytes */
- int nReq; /* Number of bytes required on leaf page */
+ i64 nReq; /* Number of bytes required on leaf page */
int nData;
SegmentWriter *pWriter = *ppWriter;
@@ -185141,13 +194761,13 @@ static int fts3SegWriterAdd(
sqlcipher_sqlite3_stmt *pStmt;
/* Allocate the SegmentWriter structure */
- pWriter = (SegmentWriter *)sqlcipher_sqlite3_malloc(sizeof(SegmentWriter));
+ pWriter = (SegmentWriter *)sqlcipher_sqlite3_malloc64(sizeof(SegmentWriter));
if( !pWriter ) return SQLITE_NOMEM;
memset(pWriter, 0, sizeof(SegmentWriter));
*ppWriter = pWriter;
/* Allocate a buffer in which to accumulate data */
- pWriter->aData = (char *)sqlcipher_sqlite3_malloc(p->nNodeSize);
+ pWriter->aData = (char *)sqlcipher_sqlite3_malloc64(p->nNodeSize);
if( !pWriter->aData ) return SQLITE_NOMEM;
pWriter->nSize = p->nNodeSize;
@@ -185222,7 +194842,7 @@ static int fts3SegWriterAdd(
** the buffer to make it large enough.
*/
if( nReq>pWriter->nSize ){
- char *aNew = sqlcipher_sqlite3_realloc(pWriter->aData, nReq);
+ char *aNew = sqlcipher_sqlite3_realloc64(pWriter->aData, nReq);
if( !aNew ) return SQLITE_NOMEM;
pWriter->aData = aNew;
pWriter->nSize = nReq;
@@ -185247,7 +194867,7 @@ static int fts3SegWriterAdd(
*/
if( isCopyTerm ){
if( nTerm>pWriter->nMalloc ){
- char *zNew = sqlcipher_sqlite3_realloc(pWriter->zMalloc, nTerm*2);
+ char *zNew = sqlcipher_sqlite3_realloc64(pWriter->zMalloc, (i64)nTerm*2);
if( !zNew ){
return SQLITE_NOMEM;
}
@@ -185555,12 +195175,12 @@ static void fts3ColumnFilter(
static int fts3MsrBufferData(
Fts3MultiSegReader *pMsr, /* Multi-segment-reader handle */
char *pList,
- int nList
+ i64 nList
){
if( nList>pMsr->nBuffer ){
char *pNew;
pMsr->nBuffer = nList*2;
- pNew = (char *)sqlcipher_sqlite3_realloc(pMsr->aBuffer, pMsr->nBuffer);
+ pNew = (char *)sqlcipher_sqlite3_realloc64(pMsr->aBuffer, pMsr->nBuffer);
if( !pNew ) return SQLITE_NOMEM;
pMsr->aBuffer = pNew;
}
@@ -185616,7 +195236,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Fts3MsrIncrNext(
fts3SegReaderSort(pMsr->apSegment, nMerge, j, xCmp);
if( nList>0 && fts3SegReaderIsPending(apSegment[0]) ){
- rc = fts3MsrBufferData(pMsr, pList, nList+1);
+ rc = fts3MsrBufferData(pMsr, pList, (i64)nList+1);
if( rc!=SQLITE_OK ) return rc;
assert( (pMsr->aBuffer[nList] & 0xFE)==0x00 );
pList = pMsr->aBuffer;
@@ -185753,11 +195373,11 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr)
return SQLITE_OK;
}
-static int fts3GrowSegReaderBuffer(Fts3MultiSegReader *pCsr, int nReq){
+static int fts3GrowSegReaderBuffer(Fts3MultiSegReader *pCsr, i64 nReq){
if( nReq>pCsr->nBuffer ){
char *aNew;
pCsr->nBuffer = nReq*2;
- aNew = sqlcipher_sqlite3_realloc(pCsr->aBuffer, pCsr->nBuffer);
+ aNew = sqlcipher_sqlite3_realloc64(pCsr->aBuffer, pCsr->nBuffer);
if( !aNew ){
return SQLITE_NOMEM;
}
@@ -185848,7 +195468,8 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Fts3SegReaderStep(
){
pCsr->nDoclist = apSegment[0]->nDoclist;
if( fts3SegReaderIsPending(apSegment[0]) ){
- rc = fts3MsrBufferData(pCsr, apSegment[0]->aDoclist, pCsr->nDoclist);
+ rc = fts3MsrBufferData(pCsr, apSegment[0]->aDoclist,
+ (i64)pCsr->nDoclist);
pCsr->aDoclist = pCsr->aBuffer;
}else{
pCsr->aDoclist = apSegment[0]->aDoclist;
@@ -185901,7 +195522,8 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Fts3SegReaderStep(
nByte = sqlcipher_sqlite3Fts3VarintLen(iDelta) + (isRequirePos?nList+1:0);
- rc = fts3GrowSegReaderBuffer(pCsr, nByte+nDoclist);
+ rc = fts3GrowSegReaderBuffer(pCsr,
+ (i64)nByte+nDoclist+FTS3_NODE_PADDING);
if( rc ) return rc;
if( isFirst ){
@@ -185927,7 +195549,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Fts3SegReaderStep(
fts3SegReaderSort(apSegment, nMerge, j, xCmp);
}
if( nDoclist>0 ){
- rc = fts3GrowSegReaderBuffer(pCsr, nDoclist+FTS3_NODE_PADDING);
+ rc = fts3GrowSegReaderBuffer(pCsr, (i64)nDoclist+FTS3_NODE_PADDING);
if( rc ) return rc;
memset(&pCsr->aBuffer[nDoclist], 0, FTS3_NODE_PADDING);
pCsr->aDoclist = pCsr->aBuffer;
@@ -186640,7 +196262,7 @@ struct NodeReader {
static void blobGrowBuffer(Blob *pBlob, int nMin, int *pRc){
if( *pRc==SQLITE_OK && nMin>pBlob->nAlloc ){
int nAlloc = nMin;
- char *a = (char *)sqlcipher_sqlite3_realloc(pBlob->a, nAlloc);
+ char *a = (char *)sqlcipher_sqlite3_realloc64(pBlob->a, nAlloc);
if( a ){
pBlob->nAlloc = nAlloc;
pBlob->a = a;
@@ -186681,7 +196303,7 @@ static int nodeReaderNext(NodeReader *p){
return FTS_CORRUPT_VTAB;
}
blobGrowBuffer(&p->term, nPrefix+nSuffix, &rc);
- if( rc==SQLITE_OK ){
+ if( rc==SQLITE_OK && ALWAYS(p->term.a!=0) ){
memcpy(&p->term.a[nPrefix], &p->aNode[p->iOff], nSuffix);
p->term.n = nPrefix+nSuffix;
p->iOff += nSuffix;
@@ -186789,6 +196411,8 @@ static int fts3IncrmergePush(
pBlk->n += sqlcipher_sqlite3Fts3PutVarint(&pBlk->a[pBlk->n], nPrefix);
}
pBlk->n += sqlcipher_sqlite3Fts3PutVarint(&pBlk->a[pBlk->n], nSuffix);
+ assert( nPrefix+nSuffix<=nTerm );
+ assert( nPrefix>=0 );
memcpy(&pBlk->a[pBlk->n], &zTerm[nPrefix], nSuffix);
pBlk->n += nSuffix;
@@ -186911,6 +196535,7 @@ static int fts3IncrmergeAppend(
pLeaf = &pWriter->aNodeWriter[0];
nPrefix = fts3PrefixCompress(pLeaf->key.a, pLeaf->key.n, zTerm, nTerm);
nSuffix = nTerm - nPrefix;
+ if(nSuffix<=0 ) return FTS_CORRUPT_VTAB;
nSpace = sqlcipher_sqlite3Fts3VarintLen(nPrefix);
nSpace += sqlcipher_sqlite3Fts3VarintLen(nSuffix) + nSuffix;
@@ -187075,7 +196700,11 @@ static int fts3TermCmp(
int nCmp = MIN(nLhs, nRhs);
int res;
- res = (nCmp ? memcmp(zLhs, zRhs, nCmp) : 0);
+ if( nCmp && ALWAYS(zLhs) && ALWAYS(zRhs) ){
+ res = memcmp(zLhs, zRhs, nCmp);
+ }else{
+ res = 0;
+ }
if( res==0 ) res = nLhs - nRhs;
return res;
@@ -187233,17 +196862,20 @@ static int fts3IncrmergeLoad(
while( reader.aNode && rc==SQLITE_OK ) rc = nodeReaderNext(&reader);
blobGrowBuffer(&pNode->key, reader.term.n, &rc);
if( rc==SQLITE_OK ){
- memcpy(pNode->key.a, reader.term.a, reader.term.n);
+ assert_fts3_nc( reader.term.n>0 || reader.aNode==0 );
+ if( reader.term.n>0 ){
+ memcpy(pNode->key.a, reader.term.a, reader.term.n);
+ }
pNode->key.n = reader.term.n;
if( i>0 ){
char *aBlock = 0;
int nBlock = 0;
pNode = &pWriter->aNodeWriter[i-1];
pNode->iBlock = reader.iChild;
- rc = sqlcipher_sqlite3Fts3ReadBlock(p, reader.iChild, &aBlock, &nBlock, 0);
+ rc = sqlcipher_sqlite3Fts3ReadBlock(p, reader.iChild, &aBlock, &nBlock,0);
blobGrowBuffer(&pNode->block,
MAX(nBlock, p->nNodeSize)+FTS3_NODE_PADDING, &rc
- );
+ );
if( rc==SQLITE_OK ){
memcpy(pNode->block.a, aBlock, nBlock);
pNode->block.n = nBlock;
@@ -187427,7 +197059,7 @@ static int fts3RepackSegdirLevel(
if( nIdx>=nAlloc ){
int *aNew;
nAlloc += 16;
- aNew = sqlcipher_sqlite3_realloc(aIdx, nAlloc*sizeof(int));
+ aNew = sqlcipher_sqlite3_realloc64(aIdx, nAlloc*sizeof(int));
if( !aNew ){
rc = SQLITE_NOMEM;
break;
@@ -187716,7 +197348,7 @@ static int fts3IncrmergeHintLoad(Fts3Table *p, Blob *pHint){
if( aHint ){
blobGrowBuffer(pHint, nHint, &rc);
if( rc==SQLITE_OK ){
- memcpy(pHint->a, aHint, nHint);
+ if( ALWAYS(pHint->a!=0) ) memcpy(pHint->a, aHint, nHint);
pHint->n = nHint;
}
}
@@ -187801,7 +197433,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int
/* Allocate space for the cursor, filter and writer objects */
const int nAlloc = sizeof(*pCsr) + sizeof(*pFilter) + sizeof(*pWriter);
- pWriter = (IncrmergeWriter *)sqlcipher_sqlite3_malloc(nAlloc);
+ pWriter = (IncrmergeWriter *)sqlcipher_sqlite3_malloc64(nAlloc);
if( !pWriter ) return SQLITE_NOMEM;
pFilter = (Fts3SegFilter *)&pWriter[1];
pCsr = (Fts3MultiSegReader *)&pFilter[1];
@@ -188437,7 +198069,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Fts3DeferredTokenList(
return SQLITE_OK;
}
- pRet = (char *)sqlcipher_sqlite3_malloc(p->pList->nData);
+ pRet = (char *)sqlcipher_sqlite3_malloc64(p->pList->nData);
if( !pRet ) return SQLITE_NOMEM;
nSkip = sqlcipher_sqlite3Fts3GetVarint(p->pList->aData, &dummy);
@@ -188457,7 +198089,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Fts3DeferToken(
int iCol /* Column that token must appear in (or -1) */
){
Fts3DeferredToken *pDeferred;
- pDeferred = sqlcipher_sqlite3_malloc(sizeof(*pDeferred));
+ pDeferred = sqlcipher_sqlite3_malloc64(sizeof(*pDeferred));
if( !pDeferred ){
return SQLITE_NOMEM;
}
@@ -188712,6 +198344,10 @@ SQLITE_PRIVATE int sqlcipher_sqlite3Fts3Optimize(Fts3Table *p){
/* #include <string.h> */
/* #include <assert.h> */
+#ifndef SQLITE_AMALGAMATION
+typedef sqlcipher_sqlite3_int64 i64;
+#endif
+
/*
** Characters that may appear in the second argument to matchinfo().
*/
@@ -188762,9 +198398,9 @@ struct SnippetIter {
struct SnippetPhrase {
int nToken; /* Number of tokens in phrase */
char *pList; /* Pointer to start of phrase position list */
- int iHead; /* Next value in position list */
+ i64 iHead; /* Next value in position list */
char *pHead; /* Position list data following iHead */
- int iTail; /* Next value in trailing position list */
+ i64 iTail; /* Next value in trailing position list */
char *pTail; /* Position list data following iTail */
};
@@ -188829,9 +198465,8 @@ static MatchinfoBuffer *fts3MIBufferNew(size_t nElem, const char *zMatchinfo){
+ sizeof(MatchinfoBuffer);
sqlcipher_sqlite3_int64 nStr = strlen(zMatchinfo);
- pRet = sqlcipher_sqlite3_malloc64(nByte + nStr+1);
+ pRet = sqlcipher_sqlite3Fts3MallocZero(nByte + nStr+1);
if( pRet ){
- memset(pRet, 0, nByte);
pRet->aMatchinfo[0] = (u8*)(&pRet->aMatchinfo[1]) - (u8*)pRet;
pRet->aMatchinfo[1+nElem] = pRet->aMatchinfo[0]
+ sizeof(u32)*((int)nElem+1);
@@ -188929,7 +198564,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Fts3MIBufferFree(MatchinfoBuffer *p){
** After it returns, *piPos contains the value of the next element of the
** list and *pp is advanced to the following varint.
*/
-static void fts3GetDeltaPosition(char **pp, int *piPos){
+static void fts3GetDeltaPosition(char **pp, i64 *piPos){
int iVal;
*pp += fts3GetVarint32(*pp, &iVal);
*piPos += (iVal-2);
@@ -189038,10 +198673,10 @@ static int fts3ExprPhraseCount(Fts3Expr *pExpr){
** arguments so that it points to the first element with a value greater
** than or equal to parameter iNext.
*/
-static void fts3SnippetAdvance(char **ppIter, int *piIter, int iNext){
+static void fts3SnippetAdvance(char **ppIter, i64 *piIter, int iNext){
char *pIter = *ppIter;
if( pIter ){
- int iIter = *piIter;
+ i64 iIter = *piIter;
while( iIter<iNext ){
if( 0==(*pIter & 0xFE) ){
@@ -189124,7 +198759,7 @@ static void fts3SnippetDetails(
SnippetPhrase *pPhrase = &pIter->aPhrase[i];
if( pPhrase->pTail ){
char *pCsr = pPhrase->pTail;
- int iCsr = pPhrase->iTail;
+ i64 iCsr = pPhrase->iTail;
while( iCsr<(iStart+pIter->nSnippet) && iCsr>=iStart ){
int j;
@@ -189170,7 +198805,7 @@ static int fts3SnippetFindPositions(Fts3Expr *pExpr, int iPhrase, void *ctx){
rc = sqlcipher_sqlite3Fts3EvalPhrasePoslist(p->pCsr, pExpr, p->iCol, &pCsr);
assert( rc==SQLITE_OK || pCsr==0 );
if( pCsr ){
- int iFirst = 0;
+ i64 iFirst = 0;
pPhrase->pList = pCsr;
fts3GetDeltaPosition(&pCsr, &iFirst);
if( iFirst<0 ){
@@ -189235,11 +198870,10 @@ static int fts3BestSnippet(
** the required space using malloc().
*/
nByte = sizeof(SnippetPhrase) * nList;
- sIter.aPhrase = (SnippetPhrase *)sqlcipher_sqlite3_malloc64(nByte);
+ sIter.aPhrase = (SnippetPhrase *)sqlcipher_sqlite3Fts3MallocZero(nByte);
if( !sIter.aPhrase ){
return SQLITE_NOMEM;
}
- memset(sIter.aPhrase, 0, nByte);
/* Initialize the contents of the SnippetIter object. Then iterate through
** the set of phrases in the expression to populate the aPhrase[] array.
@@ -189803,10 +199437,12 @@ static int fts3MatchinfoLcsCb(
** position list for the next column.
*/
static int fts3LcsIteratorAdvance(LcsIterator *pIter){
- char *pRead = pIter->pRead;
+ char *pRead;
sqlcipher_sqlite3_int64 iRead;
int rc = 0;
+ if( NEVER(pIter==0) ) return 1;
+ pRead = pIter->pRead;
pRead += sqlcipher_sqlite3Fts3GetVarint(pRead, &iRead);
if( iRead==0 || iRead==1 ){
pRead = 0;
@@ -189840,9 +199476,8 @@ static int fts3MatchinfoLcs(Fts3Cursor *pCsr, MatchInfo *pInfo){
/* Allocate and populate the array of LcsIterator objects. The array
** contains one element for each matchable phrase in the query.
**/
- aIter = sqlcipher_sqlite3_malloc64(sizeof(LcsIterator) * pCsr->nPhrase);
+ aIter = sqlcipher_sqlite3Fts3MallocZero(sizeof(LcsIterator) * pCsr->nPhrase);
if( !aIter ) return SQLITE_NOMEM;
- memset(aIter, 0, sizeof(LcsIterator) * pCsr->nPhrase);
(void)fts3ExprIterate(pCsr->pExpr, fts3MatchinfoLcsCb, (void*)aIter);
for(i=0; i<pInfo->nPhrase; i++){
@@ -190234,8 +199869,8 @@ typedef struct TermOffsetCtx TermOffsetCtx;
struct TermOffset {
char *pList; /* Position-list */
- int iPos; /* Position just read from pList */
- int iOff; /* Offset of this term from read positions */
+ i64 iPos; /* Position just read from pList */
+ i64 iOff; /* Offset of this term from read positions */
};
struct TermOffsetCtx {
@@ -190254,7 +199889,7 @@ static int fts3ExprTermOffsetInit(Fts3Expr *pExpr, int iPhrase, void *ctx){
int nTerm; /* Number of tokens in phrase */
int iTerm; /* For looping through nTerm phrase terms */
char *pList; /* Pointer to position list for phrase */
- int iPos = 0; /* First position in position-list */
+ i64 iPos = 0; /* First position in position-list */
int rc;
UNUSED_PARAMETER(iPhrase);
@@ -190303,7 +199938,7 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Fts3Offsets(
if( rc!=SQLITE_OK ) goto offsets_out;
/* Allocate the array of TermOffset iterators. */
- sCtx.aTerm = (TermOffset *)sqlcipher_sqlite3_malloc64(sizeof(TermOffset)*nToken);
+ sCtx.aTerm = (TermOffset *)sqlcipher_sqlite3Fts3MallocZero(sizeof(TermOffset)*nToken);
if( 0==sCtx.aTerm ){
rc = SQLITE_NOMEM;
goto offsets_out;
@@ -190324,13 +199959,13 @@ SQLITE_PRIVATE void sqlcipher_sqlite3Fts3Offsets(
const char *zDoc;
int nDoc;
- /* Initialize the contents of sCtx.aTerm[] for column iCol. There is
- ** no way that this operation can fail, so the return code from
- ** fts3ExprIterate() can be discarded.
+ /* Initialize the contents of sCtx.aTerm[] for column iCol. This
+ ** operation may fail if the database contains corrupt records.
*/
sCtx.iCol = iCol;
sCtx.iTerm = 0;
- (void)fts3ExprIterate(pCsr->pExpr, fts3ExprTermOffsetInit, (void*)&sCtx);
+ rc = fts3ExprIterate(pCsr->pExpr, fts3ExprTermOffsetInit, (void*)&sCtx);
+ if( rc!=SQLITE_OK ) goto offsets_out;
/* Retreive the text stored in column iCol. If an SQL NULL is stored
** in column iCol, jump immediately to the next iteration of the loop.
@@ -190731,6 +200366,7 @@ static int unicodeOpen(
pCsr->aInput = (const unsigned char *)aInput;
if( aInput==0 ){
pCsr->nInput = 0;
+ pCsr->aInput = (const unsigned char*)"";
}else if( nInput<0 ){
pCsr->nInput = (int)strlen(aInput);
}else{
@@ -191228,7 +200864,7 @@ SQLITE_PRIVATE int sqlcipher_sqlite3FtsUnicodeFold(int c, int eRemoveDiacritic){
#endif /* !defined(SQLITE_DISABLE_FTS3_UNICODE) */
/************** End of fts3_unicode2.c ***************************************/
-/************** Begin file json1.c *******************************************/
+/************** Begin file json.c ********************************************/
/*
** 2015-08-12
**
@@ -191241,10 +200877,10 @@ SQLITE_PRIVATE int sqlcipher_sqlite3FtsUnicodeFold(int c, int eRemoveDiacritic){
**
******************************************************************************
**
-** This SQLite extension implements JSON functions. The interface is
-** modeled after MySQL JSON functions:
+** This SQLite JSON functions.
**
-** https://dev.mysql.com/doc/refman/5.7/en/json.html
+** This file began as an extension in ext/misc/json1.c in 2015. That
+** extension proved so useful that it has now been moved into the core.
**
** For the time being, all JSON is stored as pure text. (We might add
** a JSONB type in the future which stores a binary encoding of JSON in
@@ -191252,48 +200888,8 @@ SQLITE_PRIVATE int sqlcipher_sqlite3FtsUnicodeFold(int c, int eRemoveDiacritic){
** This implementation parses JSON text at 250 MB/s, so it is hard to see
** how JSONB might improve on that.)
*/
-#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_JSON1)
-#if !defined(SQLITEINT_H)
-/* #include "sqlcipher_sqlite3ext.h" */
-#endif
-SQLITE_EXTENSION_INIT1
-/* #include <assert.h> */
-/* #include <string.h> */
-/* #include <stdlib.h> */
-/* #include <stdarg.h> */
-
-/* Mark a function parameter as unused, to suppress nuisance compiler
-** warnings. */
-#ifndef UNUSED_PARAM
-# define UNUSED_PARAM(X) (void)(X)
-#endif
-
-#ifndef LARGEST_INT64
-# define LARGEST_INT64 (0xffffffff|(((sqlcipher_sqlite3_int64)0x7fffffff)<<32))
-# define SMALLEST_INT64 (((sqlcipher_sqlite3_int64)-1) - LARGEST_INT64)
-#endif
-
-#ifndef deliberate_fall_through
-# define deliberate_fall_through
-#endif
-
-/*
-** Versions of isspace(), isalnum() and isdigit() to which it is safe
-** to pass signed char values.
-*/
-#ifdef sqlcipher_sqlite3Isdigit
- /* Use the SQLite core versions if this routine is part of the
- ** SQLite amalgamation */
-# define safe_isdigit(x) sqlcipher_sqlite3Isdigit(x)
-# define safe_isalnum(x) sqlcipher_sqlite3Isalnum(x)
-# define safe_isxdigit(x) sqlcipher_sqlite3Isxdigit(x)
-#else
- /* Use the standard library for separate compilation */
-#include <ctype.h> /* amalgamator: keep */
-# define safe_isdigit(x) isdigit((unsigned char)(x))
-# define safe_isalnum(x) isalnum((unsigned char)(x))
-# define safe_isxdigit(x) isxdigit((unsigned char)(x))
-#endif
+#ifndef SQLITE_OMIT_JSON
+/* #include "sqliteInt.h" */
/*
** Growing our own isspace() routine this way is twice as fast as
@@ -191318,15 +200914,12 @@ static const char jsonIsSpace[] = {
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,
};
-#define safe_isspace(x) (jsonIsSpace[(unsigned char)x])
+#define fast_isspace(x) (jsonIsSpace[(unsigned char)x])
-#ifndef SQLITE_AMALGAMATION
- /* Unsigned integer types. These are already defined in the sqliteInt.h,
- ** but the definitions need to be repeated for separate compilation. */
- typedef sqlcipher_sqlite3_uint64 u64;
- typedef unsigned int u32;
- typedef unsigned short int u16;
- typedef unsigned char u8;
+#if !defined(SQLITE_DEBUG) && !defined(SQLITE_COVERAGE_TEST)
+# define VVA(X)
+#else
+# define VVA(X) X
#endif
/* Objects */
@@ -191385,13 +200978,14 @@ static const char * const jsonType[] = {
struct JsonNode {
u8 eType; /* One of the JSON_ type values */
u8 jnFlags; /* JNODE flags */
+ u8 eU; /* Which union element to use */
u32 n; /* Bytes of content, or number of sub-nodes */
union {
- const char *zJContent; /* Content for INT, REAL, and STRING */
- u32 iAppend; /* More terms for ARRAY and OBJECT */
- u32 iKey; /* Key for ARRAY objects in json_tree() */
- u32 iReplace; /* Replacement content for JNODE_REPLACE */
- JsonNode *pPatch; /* Node chain of patch for JNODE_PATCH */
+ const char *zJContent; /* 1: Content for INT, REAL, and STRING */
+ u32 iAppend; /* 2: More terms for ARRAY and OBJECT */
+ u32 iKey; /* 3: Key for ARRAY objects in json_tree() */
+ u32 iReplace; /* 4: Replacement content for JNODE_REPLACE */
+ JsonNode *pPatch; /* 5: Node chain of patch for JNODE_PATCH */
} u;
};
@@ -191530,7 +201124,7 @@ static void jsonAppendSeparator(JsonString *p){
*/
static void jsonAppendString(JsonString *p, const char *zIn, u32 N){
u32 i;
- if( (N+p->nUsed+2 >= p->nAlloc) && jsonGrow(p,N+2)!=0 ) return;
+ if( zIn==0 || ((N+p->nUsed+2 >= p->nAlloc) && jsonGrow(p,N+2)!=0) ) return;
p->zBuf[p->nUsed++] = '"';
for(i=0; i<N; i++){
unsigned char c = ((unsigned const char*)zIn)[i];
@@ -191669,11 +201263,14 @@ static void jsonRenderNode(
JsonString *pOut, /* Write JSON here */
sqlcipher_sqlite3_value **aReplace /* Replacement values */
){
+ assert( pNode!=0 );
if( pNode->jnFlags & (JNODE_REPLACE|JNODE_PATCH) ){
- if( pNode->jnFlags & JNODE_REPLACE ){
+ if( (pNode->jnFlags & JNODE_REPLACE)!=0 && ALWAYS(aReplace!=0) ){
+ assert( pNode->eU==4 );
jsonAppendValue(pOut, aReplace[pNode->u.iReplace]);
return;
}
+ assert( pNode->eU==5 );
pNode = pNode->u.pPatch;
}
switch( pNode->eType ){
@@ -191692,6 +201289,7 @@ static void jsonRenderNode(
}
case JSON_STRING: {
if( pNode->jnFlags & JNODE_RAW ){
+ assert( pNode->eU==1 );
jsonAppendString(pOut, pNode->u.zJContent, pNode->n);
break;
}
@@ -191699,6 +201297,7 @@ static void jsonRenderNode(
}
case JSON_REAL:
case JSON_INT: {
+ assert( pNode->eU==1 );
jsonAppendRaw(pOut, pNode->u.zJContent, pNode->n);
break;
}
@@ -191714,6 +201313,7 @@ static void jsonRenderNode(
j += jsonNodeSize(&pNode[j]);
}
if( (pNode->jnFlags & JNODE_APPEND)==0 ) break;
+ assert( pNode->eU==2 );
pNode = &pNode[pNode->u.iAppend];
j = 1;
}
@@ -191734,6 +201334,7 @@ static void jsonRenderNode(
j += 1 + jsonNodeSize(&pNode[j+1]);
}
if( (pNode->jnFlags & JNODE_APPEND)==0 ) break;
+ assert( pNode->eU==2 );
pNode = &pNode[pNode->u.iAppend];
j = 1;
}
@@ -191778,10 +201379,10 @@ static u8 jsonHexToInt(int h){
*/
static u32 jsonHexToInt4(const char *z){
u32 v;
- assert( safe_isxdigit(z[0]) );
- assert( safe_isxdigit(z[1]) );
- assert( safe_isxdigit(z[2]) );
- assert( safe_isxdigit(z[3]) );
+ assert( sqlcipher_sqlite3Isxdigit(z[0]) );
+ assert( sqlcipher_sqlite3Isxdigit(z[1]) );
+ assert( sqlcipher_sqlite3Isxdigit(z[2]) );
+ assert( sqlcipher_sqlite3Isxdigit(z[3]) );
v = (jsonHexToInt(z[0])<<12)
+ (jsonHexToInt(z[1])<<8)
+ (jsonHexToInt(z[2])<<4)
@@ -191813,7 +201414,9 @@ static void jsonReturn(
}
case JSON_INT: {
sqlcipher_sqlite3_int64 i = 0;
- const char *z = pNode->u.zJContent;
+ const char *z;
+ assert( pNode->eU==1 );
+ z = pNode->u.zJContent;
if( z[0]=='-' ){ z++; }
while( z[0]>='0' && z[0]<='9' ){
unsigned v = *(z++) - '0';
@@ -191836,14 +201439,17 @@ static void jsonReturn(
sqlcipher_sqlite3_result_int64(pCtx, i);
int_done:
break;
- int_as_real: i=0; /* no break */ deliberate_fall_through
+ int_as_real: ; /* no break */ deliberate_fall_through
}
case JSON_REAL: {
double r;
#ifdef SQLITE_AMALGAMATION
- const char *z = pNode->u.zJContent;
+ const char *z;
+ assert( pNode->eU==1 );
+ z = pNode->u.zJContent;
sqlcipher_sqlite3AtoF(z, &r, sqlcipher_sqlite3Strlen30(z), SQLITE_UTF8);
#else
+ assert( pNode->eU==1 );
r = strtod(pNode->u.zJContent, 0);
#endif
sqlcipher_sqlite3_result_double(pCtx, r);
@@ -191854,6 +201460,7 @@ static void jsonReturn(
** json_insert() and json_replace() and those routines do not
** call jsonReturn() */
if( pNode->jnFlags & JNODE_RAW ){
+ assert( pNode->eU==1 );
sqlcipher_sqlite3_result_text(pCtx, pNode->u.zJContent, pNode->n,
SQLITE_TRANSIENT);
}else
@@ -191861,15 +201468,18 @@ static void jsonReturn(
assert( (pNode->jnFlags & JNODE_RAW)==0 );
if( (pNode->jnFlags & JNODE_ESCAPE)==0 ){
/* JSON formatted without any backslash-escapes */
+ assert( pNode->eU==1 );
sqlcipher_sqlite3_result_text(pCtx, pNode->u.zJContent+1, pNode->n-2,
SQLITE_TRANSIENT);
}else{
/* Translate JSON formatted string into raw text */
u32 i;
u32 n = pNode->n;
- const char *z = pNode->u.zJContent;
+ const char *z;
char *zOut;
u32 j;
+ assert( pNode->eU==1 );
+ z = pNode->u.zJContent;
zOut = sqlcipher_sqlite3_malloc( n+1 );
if( zOut==0 ){
sqlcipher_sqlite3_result_error_nomem(pCtx);
@@ -191990,12 +201600,13 @@ static int jsonParseAddNode(
const char *zContent /* Content */
){
JsonNode *p;
- if( pParse->nNode>=pParse->nAlloc ){
+ if( pParse->aNode==0 || pParse->nNode>=pParse->nAlloc ){
return jsonParseAddNodeExpand(pParse, eType, n, zContent);
}
p = &pParse->aNode[pParse->nNode];
p->eType = (u8)eType;
p->jnFlags = 0;
+ VVA( p->eU = zContent ? 1 : 0 );
p->n = n;
p->u.zJContent = zContent;
return pParse->nNode++;
@@ -192006,7 +201617,7 @@ static int jsonParseAddNode(
*/
static int jsonIs4Hex(const char *z){
int i;
- for(i=0; i<4; i++) if( !safe_isxdigit(z[i]) ) return 0;
+ for(i=0; i<4; i++) if( !sqlcipher_sqlite3Isxdigit(z[i]) ) return 0;
return 1;
}
@@ -192025,13 +201636,13 @@ static int jsonParseValue(JsonParse *pParse, u32 i){
int x;
JsonNode *pNode;
const char *z = pParse->zJson;
- while( safe_isspace(z[i]) ){ i++; }
+ while( fast_isspace(z[i]) ){ i++; }
if( (c = z[i])=='{' ){
/* Parse object */
iThis = jsonParseAddNode(pParse, JSON_OBJECT, 0, 0);
if( iThis<0 ) return -1;
for(j=i+1;;j++){
- while( safe_isspace(z[j]) ){ j++; }
+ while( fast_isspace(z[j]) ){ j++; }
if( ++pParse->iDepth > JSON_MAX_DEPTH ) return -1;
x = jsonParseValue(pParse, j);
if( x<0 ){
@@ -192044,14 +201655,14 @@ static int jsonParseValue(JsonParse *pParse, u32 i){
if( pNode->eType!=JSON_STRING ) return -1;
pNode->jnFlags |= JNODE_LABEL;
j = x;
- while( safe_isspace(z[j]) ){ j++; }
+ while( fast_isspace(z[j]) ){ j++; }
if( z[j]!=':' ) return -1;
j++;
x = jsonParseValue(pParse, j);
pParse->iDepth--;
if( x<0 ) return -1;
j = x;
- while( safe_isspace(z[j]) ){ j++; }
+ while( fast_isspace(z[j]) ){ j++; }
c = z[j];
if( c==',' ) continue;
if( c!='}' ) return -1;
@@ -192063,8 +201674,9 @@ static int jsonParseValue(JsonParse *pParse, u32 i){
/* Parse array */
iThis = jsonParseAddNode(pParse, JSON_ARRAY, 0, 0);
if( iThis<0 ) return -1;
+ memset(&pParse->aNode[iThis].u, 0, sizeof(pParse->aNode[iThis].u));
for(j=i+1;;j++){
- while( safe_isspace(z[j]) ){ j++; }
+ while( fast_isspace(z[j]) ){ j++; }
if( ++pParse->iDepth > JSON_MAX_DEPTH ) return -1;
x = jsonParseValue(pParse, j);
pParse->iDepth--;
@@ -192073,7 +201685,7 @@ static int jsonParseValue(JsonParse *pParse, u32 i){
return -1;
}
j = x;
- while( safe_isspace(z[j]) ){ j++; }
+ while( fast_isspace(z[j]) ){ j++; }
c = z[j];
if( c==',' ) continue;
if( c!=']' ) return -1;
@@ -192110,17 +201722,17 @@ static int jsonParseValue(JsonParse *pParse, u32 i){
return j+1;
}else if( c=='n'
&& strncmp(z+i,"null",4)==0
- && !safe_isalnum(z[i+4]) ){
+ && !sqlcipher_sqlite3Isalnum(z[i+4]) ){
jsonParseAddNode(pParse, JSON_NULL, 0, 0);
return i+4;
}else if( c=='t'
&& strncmp(z+i,"true",4)==0
- && !safe_isalnum(z[i+4]) ){
+ && !sqlcipher_sqlite3Isalnum(z[i+4]) ){
jsonParseAddNode(pParse, JSON_TRUE, 0, 0);
return i+4;
}else if( c=='f'
&& strncmp(z+i,"false",5)==0
- && !safe_isalnum(z[i+5]) ){
+ && !sqlcipher_sqlite3Isalnum(z[i+5]) ){
jsonParseAddNode(pParse, JSON_FALSE, 0, 0);
return i+5;
}else if( c=='-' || (c>='0' && c<='9') ){
@@ -192191,7 +201803,7 @@ static int jsonParse(
if( pParse->oom ) i = -1;
if( i>0 ){
assert( pParse->iDepth==0 );
- while( safe_isspace(zJson[i]) ) i++;
+ while( fast_isspace(zJson[i]) ) i++;
if( zJson[i] ) i = -1;
}
if( i<=0 ){
@@ -192327,6 +201939,7 @@ static JsonParse *jsonParseCached(
** a match.
*/
static int jsonLabelCompare(JsonNode *pNode, const char *zKey, u32 nKey){
+ assert( pNode->eU==1 );
if( pNode->jnFlags & JNODE_RAW ){
if( pNode->n!=nKey ) return 0;
return strncmp(pNode->u.zJContent, zKey, nKey)==0;
@@ -192373,14 +201986,15 @@ static JsonNode *jsonLookupStep(
*pzErr = zPath;
return 0;
}
+ testcase( nKey==0 );
}else{
zKey = zPath;
for(i=0; zPath[i] && zPath[i]!='.' && zPath[i]!='['; i++){}
nKey = i;
- }
- if( nKey==0 ){
- *pzErr = zPath;
- return 0;
+ if( nKey==0 ){
+ *pzErr = zPath;
+ return 0;
+ }
}
j = 1;
for(;;){
@@ -192392,6 +202006,7 @@ static JsonNode *jsonLookupStep(
j += jsonNodeSize(&pRoot[j]);
}
if( (pRoot->jnFlags & JNODE_APPEND)==0 ) break;
+ assert( pRoot->eU==2 );
iRoot += pRoot->u.iAppend;
pRoot = &pParse->aNode[iRoot];
j = 1;
@@ -192406,8 +202021,10 @@ static JsonNode *jsonLookupStep(
if( pParse->oom ) return 0;
if( pNode ){
pRoot = &pParse->aNode[iRoot];
+ assert( pRoot->eU==0 );
pRoot->u.iAppend = iStart - iRoot;
pRoot->jnFlags |= JNODE_APPEND;
+ VVA( pRoot->eU = 2 );
pParse->aNode[iLabel].jnFlags |= JNODE_RAW;
}
return pNode;
@@ -192415,7 +202032,7 @@ static JsonNode *jsonLookupStep(
}else if( zPath[0]=='[' ){
i = 0;
j = 1;
- while( safe_isdigit(zPath[j]) ){
+ while( sqlcipher_sqlite3Isdigit(zPath[j]) ){
i = i*10 + zPath[j] - '0';
j++;
}
@@ -192430,18 +202047,19 @@ static JsonNode *jsonLookupStep(
j += jsonNodeSize(&pBase[j]);
}
if( (pBase->jnFlags & JNODE_APPEND)==0 ) break;
+ assert( pBase->eU==2 );
iBase += pBase->u.iAppend;
pBase = &pParse->aNode[iBase];
j = 1;
}
j = 2;
- if( zPath[2]=='-' && safe_isdigit(zPath[3]) ){
+ if( zPath[2]=='-' && sqlcipher_sqlite3Isdigit(zPath[3]) ){
unsigned int x = 0;
j = 3;
do{
x = x*10 + zPath[j] - '0';
j++;
- }while( safe_isdigit(zPath[j]) );
+ }while( sqlcipher_sqlite3Isdigit(zPath[j]) );
if( x>i ) return 0;
i -= x;
}
@@ -192463,6 +202081,7 @@ static JsonNode *jsonLookupStep(
j += jsonNodeSize(&pRoot[j]);
}
if( (pRoot->jnFlags & JNODE_APPEND)==0 ) break;
+ assert( pRoot->eU==2 );
iRoot += pRoot->u.iAppend;
pRoot = &pParse->aNode[iRoot];
j = 1;
@@ -192478,8 +202097,10 @@ static JsonNode *jsonLookupStep(
if( pParse->oom ) return 0;
if( pNode ){
pRoot = &pParse->aNode[iRoot];
+ assert( pRoot->eU==0 );
pRoot->u.iAppend = iStart - iRoot;
pRoot->jnFlags |= JNODE_APPEND;
+ VVA( pRoot->eU = 2 );
}
return pNode;
}
@@ -192633,9 +202254,13 @@ static void jsonParseFunc(
}
jsonPrintf(100, &s,"node %3u: %7s n=%-4d up=%-4d",
i, zType, x.aNode[i].n, x.aUp[i]);
+ assert( x.aNode[i].eU==0 || x.aNode[i].eU==1 );
if( x.aNode[i].u.zJContent!=0 ){
+ assert( x.aNode[i].eU==1 );
jsonAppendRaw(&s, " ", 1);
jsonAppendRaw(&s, x.aNode[i].u.zJContent, x.aNode[i].n);
+ }else{
+ assert( x.aNode[i].eU==0 );
}
jsonAppendRaw(&s, "\n", 1);
}
@@ -192653,7 +202278,7 @@ static void jsonTest1Func(
int argc,
sqlcipher_sqlite3_value **argv
){
- UNUSED_PARAM(argc);
+ UNUSED_PARAMETER(argc);
sqlcipher_sqlite3_result_int(ctx, sqlcipher_sqlite3_value_subtype(argv[0])==JSON_SUBTYPE);
}
#endif /* SQLITE_DEBUG */
@@ -192674,7 +202299,7 @@ static void jsonQuoteFunc(
sqlcipher_sqlite3_value **argv
){
JsonString jx;
- UNUSED_PARAM(argc);
+ UNUSED_PARAMETER(argc);
jsonInit(&jx, ctx);
jsonAppendValue(&jx, argv[0]);
@@ -192746,12 +202371,33 @@ static void jsonArrayLengthFunc(
}
/*
+** Bit values for the flags passed into jsonExtractFunc() or
+** jsonSetFunc() via the user-data value.
+*/
+#define JSON_JSON 0x01 /* Result is always JSON */
+#define JSON_SQL 0x02 /* Result is always SQL */
+#define JSON_ABPATH 0x03 /* Allow abbreviated JSON path specs */
+#define JSON_ISSET 0x04 /* json_set(), not json_insert() */
+
+/*
** json_extract(JSON, PATH, ...)
+** "->"(JSON,PATH)
+** "->>"(JSON,PATH)
+**
+** Return the element described by PATH. Return NULL if that PATH element
+** is not found.
+**
+** If JSON_JSON is set or if more that one PATH argument is supplied then
+** always return a JSON representation of the result. If JSON_SQL is set,
+** then always return an SQL representation of the result. If neither flag
+** is present and argc==2, then return JSON for objects and arrays and SQL
+** for all other values.
+**
+** When multiple PATH arguments are supplied, the result is a JSON array
+** containing the result of each PATH.
**
-** Return the element described by PATH. Return NULL if there is no
-** PATH element. If there are multiple PATHs, then return a JSON array
-** with the result from each path. Throw an error if the JSON or any PATH
-** is malformed.
+** Abbreviated JSON path expressions are allows if JSON_ABPATH, for
+** compatibility with PG.
*/
static void jsonExtractFunc(
sqlcipher_sqlite3_context *ctx,
@@ -192761,35 +202407,77 @@ static void jsonExtractFunc(
JsonParse *p; /* The parse */
JsonNode *pNode;
const char *zPath;
+ int flags = SQLITE_PTR_TO_INT(sqlcipher_sqlite3_user_data(ctx));
JsonString jx;
- int i;
if( argc<2 ) return;
p = jsonParseCached(ctx, argv, ctx);
if( p==0 ) return;
- jsonInit(&jx, ctx);
- jsonAppendChar(&jx, '[');
- for(i=1; i<argc; i++){
- zPath = (const char*)sqlcipher_sqlite3_value_text(argv[i]);
- pNode = jsonLookup(p, zPath, 0, ctx);
- if( p->nErr ) break;
- if( argc>2 ){
+ if( argc==2 ){
+ /* With a single PATH argument */
+ zPath = (const char*)sqlcipher_sqlite3_value_text(argv[1]);
+ if( zPath==0 ) return;
+ if( flags & JSON_ABPATH ){
+ if( zPath[0]!='$' ){
+ /* The -> and ->> operators accept abbreviated PATH arguments. This
+ ** is mostly for compatibility with PostgreSQL, but also for
+ ** convenience.
+ **
+ ** NUMBER ==> $[NUMBER] // PG compatible
+ ** LABEL ==> $.LABEL // PG compatible
+ ** [NUMBER] ==> $[NUMBER] // Not PG. Purely for convenience
+ */
+ jsonInit(&jx, ctx);
+ if( sqlcipher_sqlite3Isdigit(zPath[0]) ){
+ jsonAppendRaw(&jx, "$[", 2);
+ jsonAppendRaw(&jx, zPath, (int)strlen(zPath));
+ jsonAppendRaw(&jx, "]", 2);
+ }else{
+ jsonAppendRaw(&jx, "$.", 1 + (zPath[0]!='['));
+ jsonAppendRaw(&jx, zPath, (int)strlen(zPath));
+ jsonAppendChar(&jx, 0);
+ }
+ pNode = jx.bErr ? 0 : jsonLookup(p, jx.zBuf, 0, ctx);
+ jsonReset(&jx);
+ }else{
+ pNode = jsonLookup(p, zPath, 0, ctx);
+ }
+ if( pNode ){
+ if( flags & JSON_JSON ){
+ jsonReturnJson(pNode, ctx, 0);
+ }else{
+ jsonReturn(pNode, ctx, 0);
+ sqlcipher_sqlite3_result_subtype(ctx, 0);
+ }
+ }
+ }else{
+ pNode = jsonLookup(p, zPath, 0, ctx);
+ if( p->nErr==0 && pNode ) jsonReturn(pNode, ctx, 0);
+ }
+ }else{
+ /* Two or more PATH arguments results in a JSON array with each
+ ** element of the array being the value selected by one of the PATHs */
+ int i;
+ jsonInit(&jx, ctx);
+ jsonAppendChar(&jx, '[');
+ for(i=1; i<argc; i++){
+ zPath = (const char*)sqlcipher_sqlite3_value_text(argv[i]);
+ pNode = jsonLookup(p, zPath, 0, ctx);
+ if( p->nErr ) break;
jsonAppendSeparator(&jx);
if( pNode ){
jsonRenderNode(pNode, &jx, 0);
}else{
jsonAppendRaw(&jx, "null", 4);
}
- }else if( pNode ){
- jsonReturn(pNode, ctx, 0);
}
+ if( i==argc ){
+ jsonAppendChar(&jx, ']');
+ jsonResult(&jx);
+ sqlcipher_sqlite3_result_subtype(ctx, JSON_SUBTYPE);
+ }
+ jsonReset(&jx);
}
- if( argc>2 && i==argc ){
- jsonAppendChar(&jx, ']');
- jsonResult(&jx);
- sqlcipher_sqlite3_result_subtype(ctx, JSON_SUBTYPE);
- }
- jsonReset(&jx);
}
/* This is the RFC 7396 MergePatch algorithm.
@@ -192805,7 +202493,7 @@ static JsonNode *jsonMergePatch(
if( pPatch->eType!=JSON_OBJECT ){
return pPatch;
}
- assert( iTarget>=0 && iTarget<pParse->nNode );
+ assert( iTarget<pParse->nNode );
pTarget = &pParse->aNode[iTarget];
assert( (pPatch->jnFlags & JNODE_APPEND)==0 );
if( pTarget->eType!=JSON_OBJECT ){
@@ -192818,6 +202506,7 @@ static JsonNode *jsonMergePatch(
const char *zKey;
assert( pPatch[i].eType==JSON_STRING );
assert( pPatch[i].jnFlags & JNODE_LABEL );
+ assert( pPatch[i].eU==1 );
nKey = pPatch[i].n;
zKey = pPatch[i].u.zJContent;
assert( (pPatch[i].jnFlags & JNODE_RAW)==0 );
@@ -192834,6 +202523,12 @@ static JsonNode *jsonMergePatch(
if( pNew==0 ) return 0;
pTarget = &pParse->aNode[iTarget];
if( pNew!=&pTarget[j+1] ){
+ assert( pTarget[j+1].eU==0
+ || pTarget[j+1].eU==1
+ || pTarget[j+1].eU==2 );
+ testcase( pTarget[j+1].eU==1 );
+ testcase( pTarget[j+1].eU==2 );
+ VVA( pTarget[j+1].eU = 5 );
pTarget[j+1].u.pPatch = pNew;
pTarget[j+1].jnFlags |= JNODE_PATCH;
}
@@ -192849,9 +202544,14 @@ static JsonNode *jsonMergePatch(
if( pParse->oom ) return 0;
jsonRemoveAllNulls(pPatch);
pTarget = &pParse->aNode[iTarget];
+ assert( pParse->aNode[iRoot].eU==0 || pParse->aNode[iRoot].eU==2 );
+ testcase( pParse->aNode[iRoot].eU==2 );
pParse->aNode[iRoot].jnFlags |= JNODE_APPEND;
+ VVA( pParse->aNode[iRoot].eU = 2 );
pParse->aNode[iRoot].u.iAppend = iStart - iRoot;
iRoot = iStart;
+ assert( pParse->aNode[iPatch].eU==0 );
+ VVA( pParse->aNode[iPatch].eU = 5 );
pParse->aNode[iPatch].jnFlags |= JNODE_PATCH;
pParse->aNode[iPatch].u.pPatch = &pPatch[i+1];
}
@@ -192873,7 +202573,7 @@ static void jsonPatchFunc(
JsonParse y; /* The patch */
JsonNode *pResult; /* The result of the merge */
- UNUSED_PARAM(argc);
+ UNUSED_PARAMETER(argc);
if( jsonParse(&x, ctx, (const char*)sqlcipher_sqlite3_value_text(argv[0])) ) return;
if( jsonParse(&y, ctx, (const char*)sqlcipher_sqlite3_value_text(argv[1])) ){
jsonParseReset(&x);
@@ -192993,11 +202693,15 @@ static void jsonReplaceFunc(
pNode = jsonLookup(&x, zPath, 0, ctx);
if( x.nErr ) goto replace_err;
if( pNode ){
+ assert( pNode->eU==0 || pNode->eU==1 || pNode->eU==4 );
+ testcase( pNode->eU!=0 && pNode->eU!=1 );
pNode->jnFlags |= (u8)JNODE_REPLACE;
+ VVA( pNode->eU = 4 );
pNode->u.iReplace = i + 1;
}
}
if( x.aNode[0].jnFlags & JNODE_REPLACE ){
+ assert( x.aNode[0].eU==4 );
sqlcipher_sqlite3_result_value(ctx, argv[x.aNode[0].u.iReplace]);
}else{
jsonReturnJson(x.aNode, ctx, argv);
@@ -193006,6 +202710,7 @@ replace_err:
jsonParseReset(&x);
}
+
/*
** json_set(JSON, PATH, VALUE, ...)
**
@@ -193028,7 +202733,7 @@ static void jsonSetFunc(
const char *zPath;
u32 i;
int bApnd;
- int bIsSet = *(int*)sqlcipher_sqlite3_user_data(ctx);
+ int bIsSet = sqlcipher_sqlite3_user_data(ctx)!=0;
if( argc<1 ) return;
if( (argc&1)==0 ) {
@@ -193047,11 +202752,15 @@ static void jsonSetFunc(
}else if( x.nErr ){
goto jsonSetDone;
}else if( pNode && (bApnd || bIsSet) ){
+ testcase( pNode->eU!=0 && pNode->eU!=1 );
+ assert( pNode->eU!=3 && pNode->eU!=5 );
+ VVA( pNode->eU = 4 );
pNode->jnFlags |= (u8)JNODE_REPLACE;
pNode->u.iReplace = i + 1;
}
}
if( x.aNode[0].jnFlags & JNODE_REPLACE ){
+ assert( x.aNode[0].eU==4 );
sqlcipher_sqlite3_result_value(ctx, argv[x.aNode[0].u.iReplace]);
}else{
jsonReturnJson(x.aNode, ctx, argv);
@@ -193064,8 +202773,8 @@ jsonSetDone:
** json_type(JSON)
** json_type(JSON, PATH)
**
-** Return the top-level "type" of a JSON string. Throw an error if
-** either the JSON or PATH inputs are not well-formed.
+** Return the top-level "type" of a JSON string. json_type() raises an
+** error if either the JSON or PATH inputs are not well-formed.
*/
static void jsonTypeFunc(
sqlcipher_sqlite3_context *ctx,
@@ -193101,7 +202810,7 @@ static void jsonValidFunc(
sqlcipher_sqlite3_value **argv
){
JsonParse *p; /* The parse */
- UNUSED_PARAM(argc);
+ UNUSED_PARAMETER(argc);
p = jsonParseCached(ctx, argv, 0);
sqlcipher_sqlite3_result_int(ctx, p!=0);
}
@@ -193121,7 +202830,7 @@ static void jsonArrayStep(
sqlcipher_sqlite3_value **argv
){
JsonString *pStr;
- UNUSED_PARAM(argc);
+ UNUSED_PARAMETER(argc);
pStr = (JsonString*)sqlcipher_sqlite3_aggregate_context(ctx, sizeof(*pStr));
if( pStr ){
if( pStr->zBuf==0 ){
@@ -193129,8 +202838,8 @@ static void jsonArrayStep(
jsonAppendChar(pStr, '[');
}else if( pStr->nUsed>1 ){
jsonAppendChar(pStr, ',');
- pStr->pCtx = ctx;
}
+ pStr->pCtx = ctx;
jsonAppendValue(pStr, argv[0]);
}
}
@@ -193181,8 +202890,8 @@ static void jsonGroupInverse(
char *z;
char c;
JsonString *pStr;
- UNUSED_PARAM(argc);
- UNUSED_PARAM(argv);
+ UNUSED_PARAMETER(argc);
+ UNUSED_PARAMETER(argv);
pStr = (JsonString*)sqlcipher_sqlite3_aggregate_context(ctx, 0);
#ifdef NEVER
/* pStr is always non-NULL since jsonArrayStep() or jsonObjectStep() will
@@ -193190,11 +202899,7 @@ static void jsonGroupInverse(
if( NEVER(!pStr) ) return;
#endif
z = pStr->zBuf;
- for(i=1; (c = z[i])!=',' || inStr || nNest; i++){
- if( i>=pStr->nUsed ){
- pStr->nUsed = 1;
- return;
- }
+ for(i=1; i<pStr->nUsed && ((c = z[i])!=',' || inStr || nNest); i++){
if( c=='"' ){
inStr = !inStr;
}else if( c=='\\' ){
@@ -193204,8 +202909,13 @@ static void jsonGroupInverse(
if( c=='}' || c==']' ) nNest--;
}
}
- pStr->nUsed -= i;
- memmove(&z[1], &z[i+1], (size_t)pStr->nUsed-1);
+ if( i<pStr->nUsed ){
+ pStr->nUsed -= i;
+ memmove(&z[1], &z[i+1], (size_t)pStr->nUsed-1);
+ z[pStr->nUsed] = 0;
+ }else{
+ pStr->nUsed = 1;
+ }
}
#else
# define jsonGroupInverse 0
@@ -193225,7 +202935,7 @@ static void jsonObjectStep(
JsonString *pStr;
const char *z;
u32 n;
- UNUSED_PARAM(argc);
+ UNUSED_PARAMETER(argc);
pStr = (JsonString*)sqlcipher_sqlite3_aggregate_context(ctx, sizeof(*pStr));
if( pStr ){
if( pStr->zBuf==0 ){
@@ -193233,8 +202943,8 @@ static void jsonObjectStep(
jsonAppendChar(pStr, '{');
}else if( pStr->nUsed>1 ){
jsonAppendChar(pStr, ',');
- pStr->pCtx = ctx;
}
+ pStr->pCtx = ctx;
z = (const char*)sqlcipher_sqlite3_value_text(argv[0]);
n = (u32)sqlcipher_sqlite3_value_bytes(argv[0]);
jsonAppendString(pStr, z, n);
@@ -193316,10 +203026,10 @@ static int jsonEachConnect(
#define JEACH_JSON 8
#define JEACH_ROOT 9
- UNUSED_PARAM(pzErr);
- UNUSED_PARAM(argv);
- UNUSED_PARAM(argc);
- UNUSED_PARAM(pAux);
+ UNUSED_PARAMETER(pzErr);
+ UNUSED_PARAMETER(argv);
+ UNUSED_PARAMETER(argc);
+ UNUSED_PARAMETER(pAux);
rc = sqlcipher_sqlite3_declare_vtab(db,
"CREATE TABLE x(key,value,type,atom,id,parent,fullkey,path,"
"json HIDDEN,root HIDDEN)");
@@ -193342,7 +203052,7 @@ static int jsonEachDisconnect(sqlcipher_sqlite3_vtab *pVtab){
static int jsonEachOpenEach(sqlcipher_sqlite3_vtab *p, sqlcipher_sqlite3_vtab_cursor **ppCursor){
JsonEachCursor *pCur;
- UNUSED_PARAM(p);
+ UNUSED_PARAMETER(p);
pCur = sqlcipher_sqlite3_malloc( sizeof(*pCur) );
if( pCur==0 ) return SQLITE_NOMEM;
memset(pCur, 0, sizeof(*pCur));
@@ -193401,6 +203111,9 @@ static int jsonEachNext(sqlcipher_sqlite3_vtab_cursor *cur){
JsonNode *pUp = &p->sParse.aNode[iUp];
p->eType = pUp->eType;
if( pUp->eType==JSON_ARRAY ){
+ assert( pUp->eU==0 || pUp->eU==3 );
+ testcase( pUp->eU==3 );
+ VVA( pUp->eU = 3 );
if( iUp==p->i-1 ){
pUp->u.iKey = 0;
}else{
@@ -193429,6 +203142,33 @@ static int jsonEachNext(sqlcipher_sqlite3_vtab_cursor *cur){
return SQLITE_OK;
}
+/* Append an object label to the JSON Path being constructed
+** in pStr.
+*/
+static void jsonAppendObjectPathElement(
+ JsonString *pStr,
+ JsonNode *pNode
+){
+ int jj, nn;
+ const char *z;
+ assert( pNode->eType==JSON_STRING );
+ assert( pNode->jnFlags & JNODE_LABEL );
+ assert( pNode->eU==1 );
+ z = pNode->u.zJContent;
+ nn = pNode->n;
+ assert( nn>=2 );
+ assert( z[0]=='"' );
+ assert( z[nn-1]=='"' );
+ if( nn>2 && sqlcipher_sqlite3Isalpha(z[1]) ){
+ for(jj=2; jj<nn-1 && sqlcipher_sqlite3Isalnum(z[jj]); jj++){}
+ if( jj==nn-1 ){
+ z++;
+ nn -= 2;
+ }
+ }
+ jsonPrintf(nn+2, pStr, ".%.*s", nn, z);
+}
+
/* Append the name of the path for element i to pStr
*/
static void jsonEachComputePath(
@@ -193447,13 +203187,13 @@ static void jsonEachComputePath(
pNode = &p->sParse.aNode[i];
pUp = &p->sParse.aNode[iUp];
if( pUp->eType==JSON_ARRAY ){
+ assert( pUp->eU==3 || (pUp->eU==0 && pUp->u.iKey==0) );
+ testcase( pUp->eU==0 );
jsonPrintf(30, pStr, "[%d]", pUp->u.iKey);
}else{
assert( pUp->eType==JSON_OBJECT );
if( (pNode->jnFlags & JNODE_LABEL)==0 ) pNode--;
- assert( pNode->eType==JSON_STRING );
- assert( pNode->jnFlags & JNODE_LABEL );
- jsonPrintf(pNode->n+1, pStr, ".%.*s", pNode->n-2, pNode->u.zJContent+1);
+ jsonAppendObjectPathElement(pStr, pNode);
}
}
@@ -193474,6 +203214,7 @@ static int jsonEachColumn(
u32 iKey;
if( p->bRecursive ){
if( p->iRowid==0 ) break;
+ assert( p->sParse.aNode[p->sParse.aUp[p->i]].eU==3 );
iKey = p->sParse.aNode[p->sParse.aUp[p->i]].u.iKey;
}else{
iKey = p->iRowid;
@@ -193523,7 +203264,7 @@ static int jsonEachColumn(
if( p->eType==JSON_ARRAY ){
jsonPrintf(30, &x, "[%d]", p->iRowid);
}else if( p->eType==JSON_OBJECT ){
- jsonPrintf(pThis->n, &x, ".%.*s", pThis->n-2, pThis->u.zJContent+1);
+ jsonAppendObjectPathElement(&x, pThis);
}
}
jsonResult(&x);
@@ -193581,7 +203322,7 @@ static int jsonEachBestIndex(
/* This implementation assumes that JSON and ROOT are the last two
** columns in the table */
assert( JEACH_ROOT == JEACH_JSON+1 );
- UNUSED_PARAM(tab);
+ UNUSED_PARAMETER(tab);
aIdx[0] = aIdx[1] = -1;
pConstraint = pIdxInfo->aConstraint;
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
@@ -193590,6 +203331,7 @@ static int jsonEachBestIndex(
if( pConstraint->iColumn < JEACH_JSON ) continue;
iCol = pConstraint->iColumn - JEACH_JSON;
assert( iCol==0 || iCol==1 );
+ testcase( iCol==0 );
iMask = 1 << iCol;
if( pConstraint->usable==0 ){
unusableMask |= iMask;
@@ -193636,8 +203378,8 @@ static int jsonEachFilter(
const char *zRoot = 0;
sqlcipher_sqlite3_int64 n;
- UNUSED_PARAM(idxStr);
- UNUSED_PARAM(argc);
+ UNUSED_PARAMETER(idxStr);
+ UNUSED_PARAMETER(argc);
jsonEachCursorReset(p);
if( idxNum==0 ) return SQLITE_OK;
z = (const char*)sqlcipher_sqlite3_value_text(argv[0]);
@@ -193687,6 +203429,8 @@ static int jsonEachFilter(
p->iBegin = p->i = (int)(pNode - p->sParse.aNode);
p->eType = pNode->eType;
if( p->eType>=JSON_ARRAY ){
+ assert( pNode->eU==0 );
+ VVA( pNode->eU = 3 );
pNode->u.iKey = 0;
p->iEnd = p->i + pNode->n + 1;
if( p->bRecursive ){
@@ -193760,108 +203504,68 @@ static sqlcipher_sqlite3_module jsonTreeModule = {
0 /* xShadowName */
};
#endif /* SQLITE_OMIT_VIRTUALTABLE */
-
-/****************************************************************************
-** The following routines are the only publically visible identifiers in this
-** file. Call the following routines in order to register the various SQL
-** functions and the virtual table implemented by this file.
-****************************************************************************/
-
-SQLITE_PRIVATE int sqlcipher_sqlite3Json1Init(sqlcipher_sqlite3 *db){
- int rc = SQLITE_OK;
- unsigned int i;
- static const struct {
- const char *zName;
- int nArg;
- int flag;
- void (*xFunc)(sqlcipher_sqlite3_context*,int,sqlcipher_sqlite3_value**);
- } aFunc[] = {
- { "json", 1, 0, jsonRemoveFunc },
- { "json_array", -1, 0, jsonArrayFunc },
- { "json_array_length", 1, 0, jsonArrayLengthFunc },
- { "json_array_length", 2, 0, jsonArrayLengthFunc },
- { "json_extract", -1, 0, jsonExtractFunc },
- { "json_insert", -1, 0, jsonSetFunc },
- { "json_object", -1, 0, jsonObjectFunc },
- { "json_patch", 2, 0, jsonPatchFunc },
- { "json_quote", 1, 0, jsonQuoteFunc },
- { "json_remove", -1, 0, jsonRemoveFunc },
- { "json_replace", -1, 0, jsonReplaceFunc },
- { "json_set", -1, 1, jsonSetFunc },
- { "json_type", 1, 0, jsonTypeFunc },
- { "json_type", 2, 0, jsonTypeFunc },
- { "json_valid", 1, 0, jsonValidFunc },
-
+#endif /* !defined(SQLITE_OMIT_JSON) */
+
+/*
+** Register JSON functions.
+*/
+SQLITE_PRIVATE void sqlcipher_sqlite3RegisterJsonFunctions(void){
+#ifndef SQLITE_OMIT_JSON
+ static FuncDef aJsonFunc[] = {
+ JFUNCTION(json, 1, 0, jsonRemoveFunc),
+ JFUNCTION(json_array, -1, 0, jsonArrayFunc),
+ JFUNCTION(json_array_length, 1, 0, jsonArrayLengthFunc),
+ JFUNCTION(json_array_length, 2, 0, jsonArrayLengthFunc),
+ JFUNCTION(json_extract, -1, 0, jsonExtractFunc),
+ JFUNCTION(->, 2, JSON_JSON, jsonExtractFunc),
+ JFUNCTION(->>, 2, JSON_SQL, jsonExtractFunc),
+ JFUNCTION(json_insert, -1, 0, jsonSetFunc),
+ JFUNCTION(json_object, -1, 0, jsonObjectFunc),
+ JFUNCTION(json_patch, 2, 0, jsonPatchFunc),
+ JFUNCTION(json_quote, 1, 0, jsonQuoteFunc),
+ JFUNCTION(json_remove, -1, 0, jsonRemoveFunc),
+ JFUNCTION(json_replace, -1, 0, jsonReplaceFunc),
+ JFUNCTION(json_set, -1, JSON_ISSET, jsonSetFunc),
+ JFUNCTION(json_type, 1, 0, jsonTypeFunc),
+ JFUNCTION(json_type, 2, 0, jsonTypeFunc),
+ JFUNCTION(json_valid, 1, 0, jsonValidFunc),
#if SQLITE_DEBUG
- /* DEBUG and TESTING functions */
- { "json_parse", 1, 0, jsonParseFunc },
- { "json_test1", 1, 0, jsonTest1Func },
-#endif
+ JFUNCTION(json_parse, 1, 0, jsonParseFunc),
+ JFUNCTION(json_test1, 1, 0, jsonTest1Func),
+#endif
+ WAGGREGATE(json_group_array, 1, 0, 0,
+ jsonArrayStep, jsonArrayFinal, jsonArrayValue, jsonGroupInverse,
+ SQLITE_SUBTYPE|SQLITE_UTF8|SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS),
+ WAGGREGATE(json_group_object, 2, 0, 0,
+ jsonObjectStep, jsonObjectFinal, jsonObjectValue, jsonGroupInverse,
+ SQLITE_SUBTYPE|SQLITE_UTF8|SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS)
};
+ sqlcipher_sqlite3InsertBuiltinFuncs(aJsonFunc, ArraySize(aJsonFunc));
+#endif
+}
+
+#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_JSON)
+/*
+** Register the JSON table-valued functions
+*/
+SQLITE_PRIVATE int sqlcipher_sqlite3JsonTableFunctions(sqlcipher_sqlite3 *db){
+ int rc = SQLITE_OK;
static const struct {
- const char *zName;
- int nArg;
- void (*xStep)(sqlcipher_sqlite3_context*,int,sqlcipher_sqlite3_value**);
- void (*xFinal)(sqlcipher_sqlite3_context*);
- void (*xValue)(sqlcipher_sqlite3_context*);
- } aAgg[] = {
- { "json_group_array", 1,
- jsonArrayStep, jsonArrayFinal, jsonArrayValue },
- { "json_group_object", 2,
- jsonObjectStep, jsonObjectFinal, jsonObjectValue },
- };
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- static const struct {
- const char *zName;
- sqlcipher_sqlite3_module *pModule;
+ const char *zName;
+ sqlcipher_sqlite3_module *pModule;
} aMod[] = {
{ "json_each", &jsonEachModule },
{ "json_tree", &jsonTreeModule },
};
-#endif
- static const int enc =
- SQLITE_UTF8 |
- SQLITE_DETERMINISTIC |
- SQLITE_INNOCUOUS;
- for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){
- rc = sqlcipher_sqlite3_create_function(db, aFunc[i].zName, aFunc[i].nArg, enc,
- (void*)&aFunc[i].flag,
- aFunc[i].xFunc, 0, 0);
- }
-#ifndef SQLITE_OMIT_WINDOWFUNC
- for(i=0; i<sizeof(aAgg)/sizeof(aAgg[0]) && rc==SQLITE_OK; i++){
- rc = sqlcipher_sqlite3_create_window_function(db, aAgg[i].zName, aAgg[i].nArg,
- SQLITE_SUBTYPE | enc, 0,
- aAgg[i].xStep, aAgg[i].xFinal,
- aAgg[i].xValue, jsonGroupInverse, 0);
- }
-#endif
-#ifndef SQLITE_OMIT_VIRTUALTABLE
+ unsigned int i;
for(i=0; i<sizeof(aMod)/sizeof(aMod[0]) && rc==SQLITE_OK; i++){
rc = sqlcipher_sqlite3_create_module(db, aMod[i].zName, aMod[i].pModule, 0);
}
-#endif
return rc;
}
+#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_JSON) */
-
-#ifndef SQLITE_CORE
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-SQLITE_API int sqlcipher_sqlite3_json_init(
- sqlcipher_sqlite3 *db,
- char **pzErrMsg,
- const sqlcipher_sqlite3_api_routines *pApi
-){
- SQLITE_EXTENSION_INIT2(pApi);
- (void)pzErrMsg; /* Unused parameter */
- return sqlcipher_sqlite3Json1Init(db);
-}
-#endif
-#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_JSON1) */
-
-/************** End of json1.c ***********************************************/
+/************** End of json.c ************************************************/
/************** Begin file rtree.c *******************************************/
/*
** 2001 September 15
@@ -193929,7 +203633,11 @@ SQLITE_API int sqlcipher_sqlite3_json_init(
#endif
SQLITE_PRIVATE int sqlcipher_sqlite3GetToken(const unsigned char*,int*); /* In the SQLite core */
-#ifndef SQLITE_AMALGAMATION
+/*
+** If building separately, we will need some setup that is normally
+** found in sqliteInt.h
+*/
+#if !defined(SQLITE_AMALGAMATION)
#include "sqlcipher_sqlite3rtree.h"
typedef sqlcipher_sqlite3_int64 i64;
typedef sqlcipher_sqlite3_uint64 u64;
@@ -193942,7 +203650,20 @@ typedef unsigned int u32;
#if defined(NDEBUG) && defined(SQLITE_DEBUG)
# undef NDEBUG
#endif
+#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
+# define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1
#endif
+#if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS)
+# 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
+#endif /* !defined(SQLITE_AMALGAMATION) */
/* #include <string.h> */
/* #include <stdio.h> */
@@ -194000,7 +203721,9 @@ struct Rtree {
u8 nBytesPerCell; /* Bytes consumed per cell */
u8 inWrTrans; /* True if inside write transaction */
u8 nAux; /* # of auxiliary columns in %_rowid */
+#ifdef SQLITE_ENABLE_GEOPOLY
u8 nAuxNotNull; /* Number of initial not-null aux columns */
+#endif
#ifdef SQLITE_DEBUG
u8 bCorrupt; /* Shadow table corruption detected */
#endif
@@ -194282,7 +204005,12 @@ struct RtreeMatchArg {
** it is not, make it a no-op.
*/
#ifndef SQLITE_AMALGAMATION
-# define testcase(X)
+# if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_DEBUG)
+ unsigned int sqlcipher_sqlite3RtreeTestcase = 0;
+# define testcase(X) if( X ){ sqlcipher_sqlite3RtreeTestcase += __LINE__; }
+# else
+# define testcase(X)
+# endif
#endif
/*
@@ -194532,18 +204260,6 @@ static void nodeBlobReset(Rtree *pRtree){
}
/*
-** Check to see if pNode is the same as pParent or any of the parents
-** of pParent.
-*/
-static int nodeInParentChain(const RtreeNode *pNode, const RtreeNode *pParent){
- do{
- if( pNode==pParent ) return 1;
- pParent = pParent->pParent;
- }while( pParent );
- return 0;
-}
-
-/*
** Obtain a reference to an r-tree node.
*/
static int nodeAcquire(
@@ -194559,14 +204275,7 @@ static int nodeAcquire(
** increase its reference count and return it.
*/
if( (pNode = nodeHashLookup(pRtree, iNode))!=0 ){
- if( pParent && !pNode->pParent ){
- if( nodeInParentChain(pNode, pParent) ){
- RTREE_IS_CORRUPT(pRtree);
- return SQLITE_CORRUPT_VTAB;
- }
- pParent->nRef++;
- pNode->pParent = pParent;
- }else if( pParent && pNode->pParent && pParent!=pNode->pParent ){
+ if( pParent && pParent!=pNode->pParent ){
RTREE_IS_CORRUPT(pRtree);
return SQLITE_CORRUPT_VTAB;
}
@@ -194624,7 +204333,7 @@ static int nodeAcquire(
** are the leaves, and so on. If the depth as specified on the root node
** is greater than RTREE_MAX_DEPTH, the r-tree structure must be corrupt.
*/
- if( pNode && rc==SQLITE_OK && iNode==1 ){
+ if( rc==SQLITE_OK && pNode && iNode==1 ){
pRtree->iDepth = readInt16(pNode->zData);
if( pRtree->iDepth>RTREE_MAX_DEPTH ){
rc = SQLITE_CORRUPT_VTAB;
@@ -195147,20 +204856,29 @@ static void rtreeNonleafConstraint(
switch( p->op ){
case RTREE_TRUE: return; /* Always satisfied */
case RTREE_FALSE: break; /* Never satisfied */
+ case RTREE_EQ:
+ RTREE_DECODE_COORD(eInt, pCellData, val);
+ /* val now holds the lower bound of the coordinate pair */
+ if( p->u.rValue>=val ){
+ pCellData += 4;
+ RTREE_DECODE_COORD(eInt, pCellData, val);
+ /* val now holds the upper bound of the coordinate pair */
+ if( p->u.rValue<=val ) return;
+ }
+ break;
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 */
+ break;
- default: /* RTREE_GT or RTREE_GE, or fallthrough of RTREE_EQ */
+ default:
pCellData += 4;
RTREE_DECODE_COORD(eInt, pCellData, val);
/* val now holds the upper bound of the coordinate pair */
if( p->u.rValue<=val ) return;
+ break;
}
*peWithin = NOT_WITHIN;
}
@@ -195230,11 +204948,12 @@ static int nodeRowidIndex(
*/
static int nodeParentIndex(Rtree *pRtree, RtreeNode *pNode, int *piIndex){
RtreeNode *pParent = pNode->pParent;
- if( pParent ){
+ if( ALWAYS(pParent) ){
return nodeRowidIndex(pRtree, pParent, pNode->iNode, piIndex);
+ }else{
+ *piIndex = -1;
+ return SQLITE_OK;
}
- *piIndex = -1;
- return SQLITE_OK;
}
/*
@@ -195357,7 +205076,8 @@ static RtreeSearchPoint *rtreeSearchPointNew(
pNew = rtreeEnqueue(pCur, rScore, iLevel);
if( pNew==0 ) return 0;
ii = (int)(pNew - pCur->aPoint) + 1;
- if( ii<RTREE_CACHE_SZ ){
+ assert( ii==1 );
+ if( ALWAYS(ii<RTREE_CACHE_SZ) ){
assert( pCur->aNode[ii]==0 );
pCur->aNode[ii] = pCur->aNode[0];
}else{
@@ -195418,7 +205138,7 @@ static void rtreeSearchPointPop(RtreeCursor *p){
if( p->bPoint ){
p->anQueue[p->sPoint.iLevel]--;
p->bPoint = 0;
- }else if( p->nPoint ){
+ }else if( ALWAYS(p->nPoint) ){
p->anQueue[p->aPoint[0].iLevel]--;
n = --p->nPoint;
p->aPoint[0] = p->aPoint[n];
@@ -195559,7 +205279,7 @@ static int rtreeRowid(sqlcipher_sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *
RtreeSearchPoint *p = rtreeSearchPointFirst(pCsr);
int rc = SQLITE_OK;
RtreeNode *pNode = rtreeNodeOfFirstSearchPoint(pCsr, &rc);
- if( rc==SQLITE_OK && p ){
+ if( rc==SQLITE_OK && ALWAYS(p) ){
*pRowid = nodeGetRowid(RTREE_OF_CURSOR(pCsr), pNode, p->iCell);
}
return rc;
@@ -195577,7 +205297,7 @@ static int rtreeColumn(sqlcipher_sqlite3_vtab_cursor *cur, sqlcipher_sqlite3_con
RtreeNode *pNode = rtreeNodeOfFirstSearchPoint(pCsr, &rc);
if( rc ) return rc;
- if( p==0 ) return SQLITE_OK;
+ if( NEVER(p==0) ) return SQLITE_OK;
if( i==0 ){
sqlcipher_sqlite3_result_int64(ctx, nodeGetRowid(pRtree, pNode, p->iCell));
}else if( i<=pRtree->nDim2 ){
@@ -195776,8 +205496,11 @@ static int rtreeFilter(
}
if( rc==SQLITE_OK ){
RtreeSearchPoint *pNew;
+ assert( pCsr->bPoint==0 ); /* Due to the resetCursor() call above */
pNew = rtreeSearchPointNew(pCsr, RTREE_ZERO, (u8)(pRtree->iDepth+1));
- if( pNew==0 ) return SQLITE_NOMEM;
+ if( NEVER(pNew==0) ){ /* Because pCsr->bPoint was FALSE */
+ return SQLITE_NOMEM;
+ }
pNew->id = 1;
pNew->iCell = 0;
pNew->eWithin = PARTLY_WITHIN;
@@ -195854,7 +205577,7 @@ static int rtreeBestIndex(sqlcipher_sqlite3_vtab *tab, sqlcipher_sqlite3_index_i
struct sqlcipher_sqlite3_index_constraint *p = &pIdxInfo->aConstraint[ii];
if( bMatch==0 && p->usable
- && p->iColumn==0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ
+ && p->iColumn<=0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ
){
/* We have an equality constraint on the rowid. Use strategy 1. */
int jj;
@@ -196060,7 +205783,7 @@ static int ChooseLeaf(
int nCell = NCELL(pNode);
RtreeCell cell;
- RtreeNode *pChild;
+ RtreeNode *pChild = 0;
RtreeCell *aCell = 0;
@@ -196107,12 +205830,19 @@ static int AdjustTree(
){
RtreeNode *p = pNode;
int cnt = 0;
+ int rc;
while( p->pParent ){
RtreeNode *pParent = p->pParent;
RtreeCell cell;
int iCell;
- if( (++cnt)>1000 || nodeParentIndex(pRtree, p, &iCell) ){
+ cnt++;
+ if( NEVER(cnt>100) ){
+ RTREE_IS_CORRUPT(pRtree);
+ return SQLITE_CORRUPT_VTAB;
+ }
+ rc = nodeParentIndex(pRtree, p, &iCell);
+ if( NEVER(rc!=SQLITE_OK) ){
RTREE_IS_CORRUPT(pRtree);
return SQLITE_CORRUPT_VTAB;
}
@@ -196401,12 +206131,17 @@ static int updateMapping(
xSetMapping = ((iHeight==0)?rowidWrite:parentWrite);
if( iHeight>0 ){
RtreeNode *pChild = nodeHashLookup(pRtree, iRowid);
+ RtreeNode *p;
+ for(p=pNode; p; p=p->pParent){
+ if( p==pChild ) return SQLITE_CORRUPT_VTAB;
+ }
if( pChild ){
nodeRelease(pRtree, pChild->pParent);
nodeReference(pNode);
pChild->pParent = pNode;
}
}
+ if( NEVER(pNode==0) ) return SQLITE_ERROR;
return xSetMapping(pRtree, iRowid, pNode->iNode);
}
@@ -196496,11 +206231,12 @@ static int SplitNode(
RtreeNode *pParent = pLeft->pParent;
int iCell;
rc = nodeParentIndex(pRtree, pLeft, &iCell);
- if( rc==SQLITE_OK ){
+ if( ALWAYS(rc==SQLITE_OK) ){
nodeOverwriteCell(pRtree, pParent, &leftbbox, iCell);
rc = AdjustTree(pRtree, pParent, &leftbbox);
+ assert( rc==SQLITE_OK );
}
- if( rc!=SQLITE_OK ){
+ if( NEVER(rc!=SQLITE_OK) ){
goto splitnode_out;
}
}
@@ -196575,7 +206311,7 @@ static int fixLeafParent(Rtree *pRtree, RtreeNode *pLeaf){
*/
iNode = sqlcipher_sqlite3_column_int64(pRtree->pReadParent, 0);
for(pTest=pLeaf; pTest && pTest->iNode!=iNode; pTest=pTest->pParent);
- if( !pTest ){
+ if( pTest==0 ){
rc2 = nodeAcquire(pRtree, iNode, 0, &pChild->pParent);
}
}
@@ -196606,6 +206342,7 @@ static int removeNode(Rtree *pRtree, RtreeNode *pNode, int iHeight){
pParent = pNode->pParent;
pNode->pParent = 0;
rc = deleteCell(pRtree, pParent, iCell, iHeight+1);
+ testcase( rc!=SQLITE_OK );
}
rc2 = nodeRelease(pRtree, pParent);
if( rc==SQLITE_OK ){
@@ -196828,7 +206565,7 @@ static int rtreeInsertCell(
}
}else{
rc = AdjustTree(pRtree, pNode, pCell);
- if( rc==SQLITE_OK ){
+ if( ALWAYS(rc==SQLITE_OK) ){
if( iHeight==0 ){
rc = rowidWrite(pRtree, pCell->iRowid, pNode->iNode);
}else{
@@ -196934,7 +206671,7 @@ static int rtreeDeleteRowid(Rtree *pRtree, sqlcipher_sqlite3_int64 iDelete){
int rc2;
RtreeNode *pChild = 0;
i64 iChild = nodeGetRowid(pRtree, pRoot, 0);
- rc = nodeAcquire(pRtree, iChild, pRoot, &pChild);
+ rc = nodeAcquire(pRtree, iChild, pRoot, &pChild); /* tag-20210916a */
if( rc==SQLITE_OK ){
rc = removeNode(pRtree, pChild, pRtree->iDepth-1);
}
@@ -197269,7 +207006,7 @@ static int rtreeQueryStat1(sqlcipher_sqlite3 *db, Rtree *pRtree){
char *zSql;
sqlcipher_sqlite3_stmt *p;
int rc;
- i64 nRow = 0;
+ i64 nRow = RTREE_MIN_ROWEST;
rc = sqlcipher_sqlite3_table_column_metadata(
db, pRtree->zDb, "sqlite_stat1",0,0,0,0,0,0
@@ -197286,20 +207023,10 @@ static int rtreeQueryStat1(sqlcipher_sqlite3 *db, Rtree *pRtree){
if( rc==SQLITE_OK ){
if( sqlcipher_sqlite3_step(p)==SQLITE_ROW ) nRow = sqlcipher_sqlite3_column_int64(p, 0);
rc = sqlcipher_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);
- }
}
sqlcipher_sqlite3_free(zSql);
}
-
+ pRtree->nRowEst = MAX(nRow, RTREE_MIN_ROWEST);
return rc;
}
@@ -197449,9 +207176,12 @@ static int rtreeSqlInit(
sqlcipher_sqlite3_str_appendf(p, "UPDATE \"%w\".\"%w_rowid\"SET ", zDb, zPrefix);
for(ii=0; ii<pRtree->nAux; ii++){
if( ii ) sqlcipher_sqlite3_str_append(p, ",", 1);
+#ifdef SQLITE_ENABLE_GEOPOLY
if( ii<pRtree->nAuxNotNull ){
sqlcipher_sqlite3_str_appendf(p,"a%d=coalesce(?%d,a%d)",ii,ii+2,ii);
- }else{
+ }else
+#endif
+ {
sqlcipher_sqlite3_str_appendf(p,"a%d=?%d",ii,ii+2);
}
}
@@ -197716,6 +207446,7 @@ static void rtreenode(sqlcipher_sqlite3_context *ctx, int nArg, sqlcipher_sqlite
tree.nDim2 = tree.nDim*2;
tree.nBytesPerCell = 8 + 8 * tree.nDim;
node.zData = (u8 *)sqlcipher_sqlite3_value_blob(apArg[1]);
+ if( node.zData==0 ) return;
nData = sqlcipher_sqlite3_value_bytes(apArg[1]);
if( nData<4 ) return;
if( nData<NCELL(&node)*tree.nBytesPerCell ) return;
@@ -197755,11 +207486,16 @@ static void rtreedepth(sqlcipher_sqlite3_context *ctx, int nArg, sqlcipher_sqlit
UNUSED_PARAMETER(nArg);
if( sqlcipher_sqlite3_value_type(apArg[0])!=SQLITE_BLOB
|| sqlcipher_sqlite3_value_bytes(apArg[0])<2
+
){
sqlcipher_sqlite3_result_error(ctx, "Invalid argument to rtreedepth()", -1);
}else{
u8 *zBlob = (u8 *)sqlcipher_sqlite3_value_blob(apArg[0]);
- sqlcipher_sqlite3_result_int(ctx, readInt16(zBlob));
+ if( zBlob ){
+ sqlcipher_sqlite3_result_int(ctx, readInt16(zBlob));
+ }else{
+ sqlcipher_sqlite3_result_error_nomem(ctx);
+ }
}
}
@@ -198125,8 +207861,10 @@ static int rtreeCheckTable(
if( pStmt ){
nAux = sqlcipher_sqlite3_column_count(pStmt) - 2;
sqlcipher_sqlite3_finalize(pStmt);
+ }else
+ if( check.rc!=SQLITE_NOMEM ){
+ check.rc = SQLITE_OK;
}
- check.rc = SQLITE_OK;
}
/* Find number of dimensions in the rtree table. */
@@ -198261,11 +207999,7 @@ static void rtreecheck(
# define GEODEBUG(X)
#endif
-#ifndef JSON_NULL /* The following stuff repeats things found in json1 */
-/*
-** Versions of isspace(), isalnum() and isdigit() to which it is safe
-** to pass signed char values.
-*/
+/* Character class routines */
#ifdef sqlcipher_sqlite3Isdigit
/* Use the SQLite core versions if this routine is part of the
** SQLite amalgamation */
@@ -198280,6 +208014,7 @@ static void rtreecheck(
# define safe_isxdigit(x) isxdigit((unsigned char)(x))
#endif
+#ifndef JSON_NULL /* The following stuff repeats things found in json1 */
/*
** Growing our own isspace() routine this way is twice as fast as
** the library isspace() function.
@@ -198302,7 +208037,7 @@ static const char geopolyIsSpace[] = {
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,
};
-#define safe_isspace(x) (geopolyIsSpace[(unsigned char)x])
+#define fast_isspace(x) (geopolyIsSpace[(unsigned char)x])
#endif /* JSON NULL - back to original code */
/* Compiler and version */
@@ -198391,7 +208126,7 @@ static void geopolySwab32(unsigned char *a){
/* Skip whitespace. Return the next non-whitespace character. */
static char geopolySkipSpace(GeoParse *p){
- while( safe_isspace(p->z[0]) ) p->z++;
+ while( fast_isspace(p->z[0]) ) p->z++;
return p->z[0];
}
@@ -198540,11 +208275,16 @@ static GeoPoly *geopolyFuncParam(
){
GeoPoly *p = 0;
int nByte;
+ testcase( pCtx==0 );
if( sqlcipher_sqlite3_value_type(pVal)==SQLITE_BLOB
&& (nByte = sqlcipher_sqlite3_value_bytes(pVal))>=(4+6*sizeof(GeoCoord))
){
const unsigned char *a = sqlcipher_sqlite3_value_blob(pVal);
int nVertex;
+ if( a==0 ){
+ if( pCtx ) sqlcipher_sqlite3_result_error_nomem(pCtx);
+ return 0;
+ }
nVertex = (a[1]<<16) + (a[2]<<8) + a[3];
if( (a[0]==0 || a[0]==1)
&& (nVertex*2*sizeof(GeoCoord) + 4)==(unsigned int)nByte
@@ -198918,7 +208658,7 @@ static GeoPoly *geopolyBBox(
aCoord[2].f = mnY;
aCoord[3].f = mxY;
}
- }else{
+ }else if( aCoord ){
memset(aCoord, 0, sizeof(RtreeCoord)*4);
}
return pOut;
@@ -199369,11 +209109,11 @@ static int geopolyOverlap(GeoPoly *p1, GeoPoly *p2){
}else{
/* Remove a segment */
if( pActive==pThisEvent->pSeg ){
- pActive = pActive->pNext;
+ pActive = ALWAYS(pActive) ? pActive->pNext : 0;
}else{
for(pSeg=pActive; pSeg; pSeg=pSeg->pNext){
if( pSeg->pNext==pThisEvent->pSeg ){
- pSeg->pNext = pSeg->pNext->pNext;
+ pSeg->pNext = ALWAYS(pSeg->pNext) ? pSeg->pNext->pNext : 0;
break;
}
}
@@ -199617,6 +209357,7 @@ static int geopolyFilter(
RtreeCoord bbox[4];
RtreeConstraint *p;
assert( argc==1 );
+ assert( argv[0]!=0 );
geopolyBBox(0, argv[0], bbox, &rc);
if( rc ){
goto geopoly_filter_end;
@@ -199844,6 +209585,7 @@ static int geopolyUpdate(
|| !sqlcipher_sqlite3_value_nochange(aData[2]) /* UPDATE _shape */
|| oldRowid!=newRowid) /* Rowid change */
){
+ assert( aData[2]!=0 );
geopolyBBox(0, aData[2], cell.aCoord, &rc);
if( rc ){
if( rc==SQLITE_ERROR ){
@@ -199926,7 +209668,7 @@ static int geopolyUpdate(
sqlcipher_sqlite3_free(p);
nChange = 1;
}
- for(jj=1; jj<pRtree->nAux; jj++){
+ for(jj=1; jj<nData-2; jj++){
nChange++;
sqlcipher_sqlite3_bind_value(pUp, jj+2, aData[jj+2]);
}
@@ -200197,7 +209939,10 @@ SQLITE_API int sqlcipher_sqlite3_rtree_query_callback(
/* Allocate and populate the context object. */
pGeomCtx = (RtreeGeomCallback *)sqlcipher_sqlite3_malloc(sizeof(RtreeGeomCallback));
- if( !pGeomCtx ) return SQLITE_NOMEM;
+ if( !pGeomCtx ){
+ if( xDestructor ) xDestructor(pContext);
+ return SQLITE_NOMEM;
+ }
pGeomCtx->xGeom = 0;
pGeomCtx->xQueryFunc = xQueryFunc;
pGeomCtx->xDestructor = xDestructor;
@@ -200526,8 +210271,9 @@ static void icuRegexpFunc(sqlcipher_sqlite3_context *p, int nArg, sqlcipher_sqli
if( U_SUCCESS(status) ){
sqlcipher_sqlite3_set_auxdata(p, 0, pExpr, icuRegexpDelete);
- }else{
- assert(!pExpr);
+ pExpr = sqlcipher_sqlite3_get_auxdata(p, 0);
+ }
+ if( !pExpr ){
icuFunctionError(p, "uregex_open", status);
return;
}
@@ -201769,6 +211515,13 @@ SQLITE_API void sqlcipher_sqlite3rbu_destroy_vfs(const char *zName);
#endif
/*
+** Name of the URI option that causes RBU to take an exclusive lock as
+** part of the incremental checkpoint operation.
+*/
+#define RBU_EXCLUSIVE_CHECKPOINT "rbu_exclusive_checkpoint"
+
+
+/*
** The rbu_state table is used to save the state of a partially applied
** update so that it can be resumed later. The table consists of integer
** keys mapped to values as follows:
@@ -202852,7 +212605,9 @@ static void rbuTableType(
assert( p->rc==SQLITE_OK );
p->rc = prepareFreeAndCollectError(p->dbMain, &aStmt[0], &p->zErrmsg,
sqlcipher_sqlite3_mprintf(
- "SELECT (sql LIKE 'create virtual%%'), rootpage"
+ "SELECT "
+ " (sql COLLATE nocase BETWEEN 'CREATE VIRTUAL' AND 'CREATE VIRTUAM'),"
+ " rootpage"
" FROM sqlite_schema"
" WHERE name=%Q", zTab
));
@@ -203212,7 +212967,7 @@ static char *rbuVacuumTableStart(
** the caller has to use an OFFSET clause to extract only the required
** rows from the sourct table, just as it does for an RBU update operation.
*/
-char *rbuVacuumIndexStart(
+static char *rbuVacuumIndexStart(
sqlcipher_sqlite3rbu *p, /* RBU handle */
RbuObjIter *pIter /* RBU iterator object */
){
@@ -203278,7 +213033,9 @@ char *rbuVacuumIndexStart(
zSep = "";
for(iCol=0; iCol<pIter->nCol; iCol++){
const char *zQuoted = (const char*)sqlcipher_sqlite3_column_text(pSel, iCol);
- if( zQuoted[0]=='N' ){
+ if( zQuoted==0 ){
+ p->rc = SQLITE_NOMEM;
+ }else if( zQuoted[0]=='N' ){
bFailed = 1;
break;
}
@@ -204383,7 +214140,7 @@ static RbuState *rbuLoadState(sqlcipher_sqlite3rbu *p){
break;
case RBU_STATE_OALSZ:
- pRet->iOalSz = (u32)sqlcipher_sqlite3_column_int64(pStmt, 1);
+ pRet->iOalSz = sqlcipher_sqlite3_column_int64(pStmt, 1);
break;
case RBU_STATE_PHASEONESTEP:
@@ -204410,13 +214167,19 @@ static RbuState *rbuLoadState(sqlcipher_sqlite3rbu *p){
/*
** Open the database handle and attach the RBU database as "rbu". If an
** error occurs, leave an error code and message in the RBU handle.
+**
+** If argument dbMain is not NULL, then it is a database handle already
+** open on the target database. Use this handle instead of opening a new
+** one.
*/
-static void rbuOpenDatabase(sqlcipher_sqlite3rbu *p, int *pbRetry){
+static void rbuOpenDatabase(sqlcipher_sqlite3rbu *p, sqlcipher_sqlite3 *dbMain, int *pbRetry){
assert( p->rc || (p->dbMain==0 && p->dbRbu==0) );
assert( p->rc || rbuIsVacuum(p) || p->zTarget!=0 );
+ assert( dbMain==0 || rbuIsVacuum(p)==0 );
/* Open the RBU database */
p->dbRbu = rbuOpenDbhandle(p, p->zRbu, 1);
+ p->dbMain = dbMain;
if( p->rc==SQLITE_OK && rbuIsVacuum(p) ){
sqlcipher_sqlite3_file_control(p->dbRbu, "main", SQLITE_FCNTL_RBUCNT, (void*)p);
@@ -204782,15 +214545,31 @@ static void rbuCheckpointFrame(sqlcipher_sqlite3rbu *p, RbuFrame *pFrame){
/*
-** Take an EXCLUSIVE lock on the database file.
+** Take an EXCLUSIVE lock on the database file. Return SQLITE_OK if
+** successful, or an SQLite error code otherwise.
*/
-static void rbuLockDatabase(sqlcipher_sqlite3rbu *p){
- sqlcipher_sqlite3_file *pReal = p->pTargetFd->pReal;
- assert( p->rc==SQLITE_OK );
- p->rc = pReal->pMethods->xLock(pReal, SQLITE_LOCK_SHARED);
- if( p->rc==SQLITE_OK ){
- p->rc = pReal->pMethods->xLock(pReal, SQLITE_LOCK_EXCLUSIVE);
+static int rbuLockDatabase(sqlcipher_sqlite3 *db){
+ int rc = SQLITE_OK;
+ sqlcipher_sqlite3_file *fd = 0;
+ sqlcipher_sqlite3_file_control(db, "main", SQLITE_FCNTL_FILE_POINTER, &fd);
+
+ if( fd->pMethods ){
+ rc = fd->pMethods->xLock(fd, SQLITE_LOCK_SHARED);
+ if( rc==SQLITE_OK ){
+ rc = fd->pMethods->xLock(fd, SQLITE_LOCK_EXCLUSIVE);
+ }
}
+ return rc;
+}
+
+/*
+** Return true if the database handle passed as the only argument
+** was opened with the rbu_exclusive_checkpoint=1 URI parameter
+** specified. Or false otherwise.
+*/
+static int rbuExclusiveCheckpoint(sqlcipher_sqlite3 *db){
+ const char *zUri = sqlcipher_sqlite3_db_filename(db, 0);
+ return sqlcipher_sqlite3_uri_boolean(zUri, RBU_EXCLUSIVE_CHECKPOINT, 0);
}
#if defined(_WIN32_WCE)
@@ -204848,18 +214627,24 @@ static void rbuMoveOalFile(sqlcipher_sqlite3rbu *p){
** In order to ensure that there are no database readers, an EXCLUSIVE
** lock is obtained here before the *-oal is moved to *-wal.
*/
- rbuLockDatabase(p);
- if( p->rc==SQLITE_OK ){
- rbuFileSuffix3(zBase, zWal);
- rbuFileSuffix3(zBase, zOal);
+ sqlcipher_sqlite3 *dbMain = 0;
+ rbuFileSuffix3(zBase, zWal);
+ rbuFileSuffix3(zBase, zOal);
- /* Re-open the databases. */
- rbuObjIterFinalize(&p->objiter);
- sqlcipher_sqlite3_close(p->dbRbu);
- sqlcipher_sqlite3_close(p->dbMain);
- p->dbMain = 0;
- p->dbRbu = 0;
+ /* Re-open the databases. */
+ rbuObjIterFinalize(&p->objiter);
+ sqlcipher_sqlite3_close(p->dbRbu);
+ sqlcipher_sqlite3_close(p->dbMain);
+ p->dbMain = 0;
+ p->dbRbu = 0;
+ dbMain = rbuOpenDbhandle(p, p->zTarget, 1);
+ if( dbMain ){
+ assert( p->rc==SQLITE_OK );
+ p->rc = rbuLockDatabase(dbMain);
+ }
+
+ if( p->rc==SQLITE_OK ){
#if defined(_WIN32_WCE)
{
LPWSTR zWideOal;
@@ -204886,11 +214671,19 @@ static void rbuMoveOalFile(sqlcipher_sqlite3rbu *p){
#else
p->rc = rename(zOal, zWal) ? SQLITE_IOERR : SQLITE_OK;
#endif
+ }
- if( p->rc==SQLITE_OK ){
- rbuOpenDatabase(p, 0);
- rbuSetupCheckpoint(p, 0);
- }
+ if( p->rc!=SQLITE_OK
+ || rbuIsVacuum(p)
+ || rbuExclusiveCheckpoint(dbMain)==0
+ ){
+ sqlcipher_sqlite3_close(dbMain);
+ dbMain = 0;
+ }
+
+ if( p->rc==SQLITE_OK ){
+ rbuOpenDatabase(p, dbMain, 0);
+ rbuSetupCheckpoint(p, 0);
}
}
@@ -205641,9 +215434,9 @@ static sqlcipher_sqlite3rbu *openRbuHandle(
** If this is the case, it will have been checkpointed and deleted
** when the handle was closed and a second attempt to open the
** database may succeed. */
- rbuOpenDatabase(p, &bRetry);
+ rbuOpenDatabase(p, 0, &bRetry);
if( bRetry ){
- rbuOpenDatabase(p, 0);
+ rbuOpenDatabase(p, 0, 0);
}
}
@@ -205738,6 +215531,14 @@ static sqlcipher_sqlite3rbu *openRbuHandle(
}else if( p->eStage==RBU_STAGE_MOVE ){
/* no-op */
}else if( p->eStage==RBU_STAGE_CKPT ){
+ if( !rbuIsVacuum(p) && rbuExclusiveCheckpoint(p->dbMain) ){
+ /* If the rbu_exclusive_checkpoint=1 URI parameter was specified
+ ** and an incremental checkpoint is being resumed, attempt an
+ ** exclusive lock on the db file. If this fails, so be it. */
+ p->eStage = RBU_STAGE_DONE;
+ rbuLockDatabase(p->dbMain);
+ p->eStage = RBU_STAGE_CKPT;
+ }
rbuSetupCheckpoint(p, pState);
}else if( p->eStage==RBU_STAGE_DONE ){
p->rc = SQLITE_DONE;
@@ -205775,7 +215576,6 @@ SQLITE_API sqlcipher_sqlite3rbu *sqlcipher_sqlite3rbu_open(
const char *zState
){
if( zTarget==0 || zRbu==0 ){ return rbuMisuseError(); }
- /* TODO: Check that zTarget and zRbu are non-NULL */
return openRbuHandle(zTarget, zRbu, zState);
}
@@ -206486,22 +216286,24 @@ static int rbuVfsShmLock(sqlcipher_sqlite3_file *pFile, int ofst, int n, int fla
#endif
assert( p->openFlags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_TEMP_DB) );
- if( pRbu && (pRbu->eStage==RBU_STAGE_OAL || pRbu->eStage==RBU_STAGE_MOVE) ){
- /* Magic number 1 is the WAL_CKPT_LOCK lock. Preventing SQLite from
- ** taking this lock also prevents any checkpoints from occurring.
- ** todo: really, it's not clear why this might occur, as
- ** wal_autocheckpoint ought to be turned off. */
+ if( pRbu && (
+ pRbu->eStage==RBU_STAGE_OAL
+ || pRbu->eStage==RBU_STAGE_MOVE
+ || pRbu->eStage==RBU_STAGE_DONE
+ )){
+ /* Prevent SQLite from taking a shm-lock on the target file when it
+ ** is supplying heap memory to the upper layer in place of *-shm
+ ** segments. */
if( ofst==WAL_LOCK_CKPT && n==1 ) rc = SQLITE_BUSY;
}else{
int bCapture = 0;
if( pRbu && pRbu->eStage==RBU_STAGE_CAPTURE ){
bCapture = 1;
}
-
if( bCapture==0 || 0==(flags & SQLITE_SHM_UNLOCK) ){
rc = p->pReal->pMethods->xShmLock(p->pReal, ofst, n, flags);
if( bCapture && rc==SQLITE_OK ){
- pRbu->mLock |= (1 << ofst);
+ pRbu->mLock |= ((1<<n) - 1) << ofst;
}
}
}
@@ -206648,28 +216450,14 @@ static int rbuVfsOpen(
rbu_file *pDb = rbuFindMaindb(pRbuVfs, zName, 0);
if( pDb ){
if( pDb->pRbu && pDb->pRbu->eStage==RBU_STAGE_OAL ){
- /* This call is to open a *-wal file. Intead, open the *-oal. This
- ** code ensures that the string passed to xOpen() is terminated by a
- ** pair of '\0' bytes in case the VFS attempts to extract a URI
- ** parameter from it. */
- const char *zBase = zName;
- size_t nCopy;
- char *zCopy;
+ /* This call is to open a *-wal file. Intead, open the *-oal. */
+ size_t nOpen;
if( rbuIsVacuum(pDb->pRbu) ){
- zBase = sqlcipher_sqlite3_db_filename(pDb->pRbu->dbRbu, "main");
- zBase = sqlcipher_sqlite3_filename_wal(zBase);
- }
- nCopy = strlen(zBase);
- zCopy = sqlcipher_sqlite3_malloc64(nCopy+2);
- if( zCopy ){
- memcpy(zCopy, zBase, nCopy);
- zCopy[nCopy-3] = 'o';
- zCopy[nCopy] = '\0';
- zCopy[nCopy+1] = '\0';
- zOpen = (const char*)(pFd->zDel = zCopy);
- }else{
- rc = SQLITE_NOMEM;
+ zOpen = sqlcipher_sqlite3_db_filename(pDb->pRbu->dbRbu, "main");
+ zOpen = sqlcipher_sqlite3_filename_wal(zOpen);
}
+ nOpen = strlen(zOpen);
+ ((char*)zOpen)[nOpen-3] = 'o';
pFd->pRbu = pDb->pRbu;
}
pDb->pWalFd = pFd;
@@ -206991,6 +216779,15 @@ SQLITE_API sqlcipher_sqlite3_int64 sqlcipher_sqlite3rbu_temp_size(sqlcipher_sqli
&& !defined(SQLITE_OMIT_VIRTUALTABLE)
/*
+** The pager and btree modules arrange objects in memory so that there are
+** always approximately 200 bytes of addressable memory following each page
+** buffer. This way small buffer overreads caused by corrupt database pages
+** do not cause undefined behaviour. This module pads each page buffer
+** by the following number of bytes for the same purpose.
+*/
+#define DBSTAT_PAGE_PADDING_BYTES 256
+
+/*
** Page paths:
**
** The value of the 'path' column describes the path taken from the
@@ -207057,9 +216854,8 @@ struct StatCell {
/* Size information for a single btree page */
struct StatPage {
u32 iPgno; /* Page number */
- DbPage *pPg; /* Page content */
+ u8 *aPg; /* Page buffer from sqlcipher_sqlite3_malloc() */
int iCell; /* Current cell */
-
char *zPath; /* Path to this page */
/* Variables populated by statDecodePage(): */
@@ -207271,18 +217067,25 @@ static void statClearCells(StatPage *p){
}
static void statClearPage(StatPage *p){
+ u8 *aPg = p->aPg;
statClearCells(p);
- sqlcipher_sqlite3PagerUnref(p->pPg);
sqlcipher_sqlite3_free(p->zPath);
memset(p, 0, sizeof(StatPage));
+ p->aPg = aPg;
}
static void statResetCsr(StatCursor *pCsr){
int i;
- sqlcipher_sqlite3_reset(pCsr->pStmt);
+ /* In some circumstances, specifically if an OOM has occurred, the call
+ ** to sqlcipher_sqlite3_reset() may cause the pager to be reset (emptied). It is
+ ** important that statClearPage() is called to free any page refs before
+ ** this happens. dbsqlfuzz 9ed3e4e3816219d3509d711636c38542bf3f40b1. */
for(i=0; i<ArraySize(pCsr->aPage); i++){
statClearPage(&pCsr->aPage[i]);
+ sqlcipher_sqlite3_free(pCsr->aPage[i].aPg);
+ pCsr->aPage[i].aPg = 0;
}
+ sqlcipher_sqlite3_reset(pCsr->pStmt);
pCsr->iPage = 0;
sqlcipher_sqlite3_free(pCsr->zPath);
pCsr->zPath = 0;
@@ -207347,7 +217150,7 @@ static int statDecodePage(Btree *pBt, StatPage *p){
int isLeaf;
int szPage;
- u8 *aData = sqlcipher_sqlite3PagerGetData(p->pPg);
+ u8 *aData = p->aPg;
u8 *aHdr = &aData[p->iPgno==1 ? 100 : 0];
p->flags = aHdr[0];
@@ -207418,7 +217221,7 @@ static int statDecodePage(Btree *pBt, StatPage *p){
if( nPayload>(u32)nLocal ){
int j;
int nOvfl = ((nPayload - nLocal) + nUsable-4 - 1) / (nUsable - 4);
- if( iOff+nLocal>nUsable || nPayload>0x7fffffff ){
+ if( iOff+nLocal+4>nUsable || nPayload>0x7fffffff ){
goto statPageIsCorrupt;
}
pCell->nLastOvfl = (nPayload-nLocal) - (nOvfl-1) * (nUsable-4);
@@ -207478,6 +217281,38 @@ static void statSizeAndOffset(StatCursor *pCsr){
}
/*
+** Load a copy of the page data for page iPg into the buffer belonging
+** to page object pPg. Allocate the buffer if necessary. Return SQLITE_OK
+** if successful, or an SQLite error code otherwise.
+*/
+static int statGetPage(
+ Btree *pBt, /* Load page from this b-tree */
+ u32 iPg, /* Page number to load */
+ StatPage *pPg /* Load page into this object */
+){
+ int pgsz = sqlcipher_sqlite3BtreeGetPageSize(pBt);
+ DbPage *pDbPage = 0;
+ int rc;
+
+ if( pPg->aPg==0 ){
+ pPg->aPg = (u8*)sqlcipher_sqlite3_malloc(pgsz + DBSTAT_PAGE_PADDING_BYTES);
+ if( pPg->aPg==0 ){
+ return SQLITE_NOMEM_BKPT;
+ }
+ memset(&pPg->aPg[pgsz], 0, DBSTAT_PAGE_PADDING_BYTES);
+ }
+
+ rc = sqlcipher_sqlite3PagerGet(sqlcipher_sqlite3BtreePager(pBt), iPg, &pDbPage, 0);
+ if( rc==SQLITE_OK ){
+ const u8 *a = sqlcipher_sqlite3PagerGetData(pDbPage);
+ memcpy(pPg->aPg, a, pgsz);
+ sqlcipher_sqlite3PagerUnref(pDbPage);
+ }
+
+ return rc;
+}
+
+/*
** Move a DBSTAT cursor to the next entry. Normally, the next
** entry will be the next page, but in aggregated mode (pCsr->isAgg!=0),
** the next entry is the next btree.
@@ -207495,7 +217330,7 @@ static int statNext(sqlcipher_sqlite3_vtab_cursor *pCursor){
pCsr->zPath = 0;
statNextRestart:
- if( pCsr->aPage[0].pPg==0 ){
+ if( pCsr->iPage<0 ){
/* Start measuring space on the next btree */
statResetCounts(pCsr);
rc = sqlcipher_sqlite3_step(pCsr->pStmt);
@@ -207507,7 +217342,7 @@ statNextRestart:
pCsr->isEof = 1;
return sqlcipher_sqlite3_reset(pCsr->pStmt);
}
- rc = sqlcipher_sqlite3PagerGet(pPager, iRoot, &pCsr->aPage[0].pPg, 0);
+ rc = statGetPage(pBt, iRoot, &pCsr->aPage[0]);
pCsr->aPage[0].iPgno = iRoot;
pCsr->aPage[0].iCell = 0;
if( !pCsr->isAgg ){
@@ -207558,9 +217393,8 @@ statNextRestart:
if( !p->iRightChildPg || p->iCell>p->nCell ){
statClearPage(p);
- if( pCsr->iPage>0 ){
- pCsr->iPage--;
- }else if( pCsr->isAgg ){
+ pCsr->iPage--;
+ if( pCsr->isAgg && pCsr->iPage<0 ){
/* label-statNext-done: When computing aggregate space usage over
** an entire btree, this is the exit point from this function */
return SQLITE_OK;
@@ -207579,7 +217413,7 @@ statNextRestart:
}else{
p[1].iPgno = p->aCell[p->iCell].iChildPg;
}
- rc = sqlcipher_sqlite3PagerGet(pPager, p[1].iPgno, &p[1].pPg, 0);
+ rc = statGetPage(pBt, p[1].iPgno, &p[1]);
pCsr->nPage++;
p[1].iCell = 0;
if( !pCsr->isAgg ){
@@ -207709,6 +217543,7 @@ static int statFilter(
}
if( rc==SQLITE_OK ){
+ pCsr->iPage = -1;
rc = statNext(pCursor);
}
return rc;
@@ -207977,6 +217812,7 @@ static int dbpageBestIndex(sqlcipher_sqlite3_vtab *tab, sqlcipher_sqlite3_index_
){
pIdxInfo->orderByConsumed = 1;
}
+ sqlcipher_sqlite3VtabUsesAllSchemas(pIdxInfo);
return SQLITE_OK;
}
@@ -208154,7 +217990,7 @@ static int dbpageUpdate(
goto update_fail;
}
pBt = pTab->db->aDb[iDb].pBt;
- if( pgno<1 || pBt==0 || pgno>(int)sqlcipher_sqlite3BtreeLastPage(pBt) ){
+ if( pgno<1 || pBt==0 || pgno>sqlcipher_sqlite3BtreeLastPage(pBt) ){
zErr = "bad page number";
goto update_fail;
}
@@ -208282,12 +218118,15 @@ struct SessionHook {
struct sqlcipher_sqlite3_session {
sqlcipher_sqlite3 *db; /* Database handle session is attached to */
char *zDb; /* Name of database session is attached to */
+ int bEnableSize; /* True if changeset_size() enabled */
int bEnable; /* True if currently recording */
int bIndirect; /* True if all changes are indirect */
int bAutoAttach; /* True to auto-attach tables */
int rc; /* Non-zero if an error has occurred */
void *pFilterCtx; /* First argument to pass to xTableFilter */
int (*xTableFilter)(void *pCtx, const char *zTab);
+ i64 nMalloc; /* Number of bytes of data allocated */
+ i64 nMaxChangesetSize;
sqlcipher_sqlite3_value *pZeroBlob; /* Value containing X'' */
sqlcipher_sqlite3_session *pNext; /* Next session object on same db. */
SessionTable *pTable; /* List of attached tables */
@@ -208330,6 +218169,7 @@ struct sqlcipher_sqlite3_changeset_iter {
SessionBuffer tblhdr; /* Buffer to hold apValue/zTab/abPK/ */
int bPatchset; /* True if this is a patchset */
int bInvert; /* True to invert changeset */
+ int bSkipEmpty; /* Skip noop UPDATE changes */
int rc; /* Iterator error code */
sqlcipher_sqlite3_stmt *pConflict; /* Points to conflicting row, if any */
char *zTab; /* Current table */
@@ -208529,8 +218369,9 @@ struct SessionTable {
** this structure stored in a SessionTable.aChange[] hash table.
*/
struct SessionChange {
- int op; /* One of UPDATE, DELETE, INSERT */
- int bIndirect; /* True if this change is "indirect" */
+ u8 op; /* One of UPDATE, DELETE, INSERT */
+ u8 bIndirect; /* True if this change is "indirect" */
+ int nMaxSize; /* Max size of eventual changeset record */
int nRecord; /* Number of bytes in buffer aRecord[] */
u8 *aRecord; /* Buffer containing old.* record */
SessionChange *pNext; /* For hash-table collisions */
@@ -208655,7 +218496,7 @@ static int sessionSerializeValue(
if( aBuf ){
sessionVarintPut(&aBuf[1], n);
- if( n ) memcpy(&aBuf[nVarint + 1], z, n);
+ if( n>0 ) memcpy(&aBuf[nVarint + 1], z, n);
}
nByte = 1 + nVarint + n;
@@ -208671,6 +218512,26 @@ static int sessionSerializeValue(
return SQLITE_OK;
}
+/*
+** Allocate and return a pointer to a buffer nByte bytes in size. If
+** pSession is not NULL, increase the sqlcipher_sqlite3_session.nMalloc variable
+** by the number of bytes allocated.
+*/
+static void *sessionMalloc64(sqlcipher_sqlite3_session *pSession, i64 nByte){
+ void *pRet = sqlcipher_sqlite3_malloc64(nByte);
+ if( pSession ) pSession->nMalloc += sqlcipher_sqlite3_msize(pRet);
+ return pRet;
+}
+
+/*
+** Free buffer pFree, which must have been allocated by an earlier
+** call to sessionMalloc64(). If pSession is not NULL, decrease the
+** sqlcipher_sqlite3_session.nMalloc counter by the number of bytes freed.
+*/
+static void sessionFree(sqlcipher_sqlite3_session *pSession, void *pFree){
+ if( pSession ) pSession->nMalloc -= sqlcipher_sqlite3_msize(pFree);
+ sqlcipher_sqlite3_free(pFree);
+}
/*
** This macro is used to calculate hash key values for data structures. In
@@ -209138,13 +218999,19 @@ static int sessionPreupdateEqual(
** Growing the hash table in this case is a performance optimization only,
** it is not required for correct operation.
*/
-static int sessionGrowHash(int bPatchset, SessionTable *pTab){
+static int sessionGrowHash(
+ sqlcipher_sqlite3_session *pSession, /* For memory accounting. May be NULL */
+ int bPatchset,
+ SessionTable *pTab
+){
if( pTab->nChange==0 || pTab->nEntry>=(pTab->nChange/2) ){
int i;
SessionChange **apNew;
sqlcipher_sqlite3_int64 nNew = 2*(sqlcipher_sqlite3_int64)(pTab->nChange ? pTab->nChange : 128);
- apNew = (SessionChange **)sqlcipher_sqlite3_malloc64(sizeof(SessionChange *) * nNew);
+ apNew = (SessionChange**)sessionMalloc64(
+ pSession, sizeof(SessionChange*) * nNew
+ );
if( apNew==0 ){
if( pTab->nChange==0 ){
return SQLITE_ERROR;
@@ -209165,7 +219032,7 @@ static int sessionGrowHash(int bPatchset, SessionTable *pTab){
}
}
- sqlcipher_sqlite3_free(pTab->apChange);
+ sessionFree(pSession, pTab->apChange);
pTab->nChange = nNew;
pTab->apChange = apNew;
}
@@ -209199,6 +219066,7 @@ static int sessionGrowHash(int bPatchset, SessionTable *pTab){
** be freed using sqlcipher_sqlite3_free() by the caller
*/
static int sessionTableInfo(
+ sqlcipher_sqlite3_session *pSession, /* For memory accounting. May be NULL */
sqlcipher_sqlite3 *db, /* Database connection */
const char *zDb, /* Name of attached database (e.g. "main") */
const char *zThis, /* Table name */
@@ -209233,16 +219101,32 @@ static int sessionTableInfo(
}else if( rc==SQLITE_ERROR ){
zPragma = sqlcipher_sqlite3_mprintf("");
}else{
+ *pazCol = 0;
+ *pabPK = 0;
+ *pnCol = 0;
+ if( pzTab ) *pzTab = 0;
return rc;
}
}else{
zPragma = sqlcipher_sqlite3_mprintf("PRAGMA '%q'.table_info('%q')", zDb, zThis);
}
- if( !zPragma ) return SQLITE_NOMEM;
+ if( !zPragma ){
+ *pazCol = 0;
+ *pabPK = 0;
+ *pnCol = 0;
+ if( pzTab ) *pzTab = 0;
+ return SQLITE_NOMEM;
+ }
rc = sqlcipher_sqlite3_prepare_v2(db, zPragma, -1, &pStmt, 0);
sqlcipher_sqlite3_free(zPragma);
- if( rc!=SQLITE_OK ) return rc;
+ if( rc!=SQLITE_OK ){
+ *pazCol = 0;
+ *pabPK = 0;
+ *pnCol = 0;
+ if( pzTab ) *pzTab = 0;
+ return rc;
+ }
nByte = nThis + 1;
while( SQLITE_ROW==sqlcipher_sqlite3_step(pStmt) ){
@@ -209253,7 +219137,7 @@ static int sessionTableInfo(
if( rc==SQLITE_OK ){
nByte += nDbCol * (sizeof(const char *) + sizeof(u8) + 1);
- pAlloc = sqlcipher_sqlite3_malloc64(nByte);
+ pAlloc = sessionMalloc64(pSession, nByte);
if( pAlloc==0 ){
rc = SQLITE_NOMEM;
}
@@ -209296,7 +219180,7 @@ static int sessionTableInfo(
*pabPK = 0;
*pnCol = 0;
if( pzTab ) *pzTab = 0;
- sqlcipher_sqlite3_free(azCol);
+ sessionFree(pSession, azCol);
}
sqlcipher_sqlite3_finalize(pStmt);
return rc;
@@ -209318,7 +219202,7 @@ static int sessionInitTable(sqlcipher_sqlite3_session *pSession, SessionTable *p
if( pTab->nCol==0 ){
u8 *abPK;
assert( pTab->azCol==0 || pTab->abPK==0 );
- pSession->rc = sessionTableInfo(pSession->db, pSession->zDb,
+ pSession->rc = sessionTableInfo(pSession, pSession->db, pSession->zDb,
pTab->zName, &pTab->nCol, 0, &pTab->azCol, &abPK
);
if( pSession->rc==SQLITE_OK ){
@@ -209332,6 +219216,12 @@ static int sessionInitTable(sqlcipher_sqlite3_session *pSession, SessionTable *p
if( 0==sqlcipher_sqlite3_stricmp("sqlite_stat1", pTab->zName) ){
pTab->bStat1 = 1;
}
+
+ if( pSession->bEnableSize ){
+ pSession->nMaxChangesetSize += (
+ 1 + sessionVarintLen(pTab->nCol) + pTab->nCol + strlen(pTab->zName)+1
+ );
+ }
}
}
return (pSession->rc || pTab->abPK==0);
@@ -209377,6 +219267,103 @@ static int sessionStat1Depth(void *pCtx){
return p->hook.xDepth(p->hook.pCtx);
}
+static int sessionUpdateMaxSize(
+ int op,
+ sqlcipher_sqlite3_session *pSession, /* Session object pTab is attached to */
+ SessionTable *pTab, /* Table that change applies to */
+ SessionChange *pC /* Update pC->nMaxSize */
+){
+ i64 nNew = 2;
+ if( pC->op==SQLITE_INSERT ){
+ if( op!=SQLITE_DELETE ){
+ int ii;
+ for(ii=0; ii<pTab->nCol; ii++){
+ sqlcipher_sqlite3_value *p = 0;
+ pSession->hook.xNew(pSession->hook.pCtx, ii, &p);
+ sessionSerializeValue(0, p, &nNew);
+ }
+ }
+ }else if( op==SQLITE_DELETE ){
+ nNew += pC->nRecord;
+ if( sqlcipher_sqlite3_preupdate_blobwrite(pSession->db)>=0 ){
+ nNew += pC->nRecord;
+ }
+ }else{
+ int ii;
+ u8 *pCsr = pC->aRecord;
+ for(ii=0; ii<pTab->nCol; ii++){
+ int bChanged = 1;
+ int nOld = 0;
+ int eType;
+ sqlcipher_sqlite3_value *p = 0;
+ pSession->hook.xNew(pSession->hook.pCtx, ii, &p);
+ if( p==0 ){
+ return SQLITE_NOMEM;
+ }
+
+ eType = *pCsr++;
+ switch( eType ){
+ case SQLITE_NULL:
+ bChanged = sqlcipher_sqlite3_value_type(p)!=SQLITE_NULL;
+ break;
+
+ case SQLITE_FLOAT:
+ case SQLITE_INTEGER: {
+ if( eType==sqlcipher_sqlite3_value_type(p) ){
+ sqlcipher_sqlite3_int64 iVal = sessionGetI64(pCsr);
+ if( eType==SQLITE_INTEGER ){
+ bChanged = (iVal!=sqlcipher_sqlite3_value_int64(p));
+ }else{
+ double dVal;
+ memcpy(&dVal, &iVal, 8);
+ bChanged = (dVal!=sqlcipher_sqlite3_value_double(p));
+ }
+ }
+ nOld = 8;
+ pCsr += 8;
+ break;
+ }
+
+ default: {
+ int nByte;
+ nOld = sessionVarintGet(pCsr, &nByte);
+ pCsr += nOld;
+ nOld += nByte;
+ assert( eType==SQLITE_TEXT || eType==SQLITE_BLOB );
+ if( eType==sqlcipher_sqlite3_value_type(p)
+ && nByte==sqlcipher_sqlite3_value_bytes(p)
+ && (nByte==0 || 0==memcmp(pCsr, sqlcipher_sqlite3_value_blob(p), nByte))
+ ){
+ bChanged = 0;
+ }
+ pCsr += nByte;
+ break;
+ }
+ }
+
+ if( bChanged && pTab->abPK[ii] ){
+ nNew = pC->nRecord + 2;
+ break;
+ }
+
+ if( bChanged ){
+ nNew += 1 + nOld;
+ sessionSerializeValue(0, p, &nNew);
+ }else if( pTab->abPK[ii] ){
+ nNew += 2 + nOld;
+ }else{
+ nNew += 2;
+ }
+ }
+ }
+
+ if( nNew>pC->nMaxSize ){
+ int nIncr = nNew - pC->nMaxSize;
+ pC->nMaxSize = nNew;
+ pSession->nMaxChangesetSize += nIncr;
+ }
+ return SQLITE_OK;
+}
/*
** This function is only called from with a pre-update-hook reporting a
@@ -209409,7 +219396,7 @@ static void sessionPreupdateOneChange(
}
/* Grow the hash table if required */
- if( sessionGrowHash(0, pTab) ){
+ if( sessionGrowHash(pSession, 0, pTab) ){
pSession->rc = SQLITE_NOMEM;
return;
}
@@ -209450,7 +219437,6 @@ static void sessionPreupdateOneChange(
/* Create a new change object containing all the old values (if
** this is an SQLITE_UPDATE or SQLITE_DELETE), or just the PK
** values (if this is an INSERT). */
- SessionChange *pChange; /* New change object */
sqlcipher_sqlite3_int64 nByte; /* Number of bytes to allocate */
int i; /* Used to iterate through columns */
@@ -209476,13 +219462,13 @@ static void sessionPreupdateOneChange(
}
/* Allocate the change object */
- pChange = (SessionChange *)sqlcipher_sqlite3_malloc64(nByte);
- if( !pChange ){
+ pC = (SessionChange *)sessionMalloc64(pSession, nByte);
+ if( !pC ){
rc = SQLITE_NOMEM;
goto error_out;
}else{
- memset(pChange, 0, sizeof(SessionChange));
- pChange->aRecord = (u8 *)&pChange[1];
+ memset(pC, 0, sizeof(SessionChange));
+ pC->aRecord = (u8 *)&pC[1];
}
/* Populate the change object. None of the preupdate_old(),
@@ -209497,17 +219483,17 @@ static void sessionPreupdateOneChange(
}else if( pTab->abPK[i] ){
pSession->hook.xNew(pSession->hook.pCtx, i, &p);
}
- sessionSerializeValue(&pChange->aRecord[nByte], p, &nByte);
+ sessionSerializeValue(&pC->aRecord[nByte], p, &nByte);
}
/* Add the change to the hash-table */
if( pSession->bIndirect || pSession->hook.xDepth(pSession->hook.pCtx) ){
- pChange->bIndirect = 1;
+ pC->bIndirect = 1;
}
- pChange->nRecord = nByte;
- pChange->op = op;
- pChange->pNext = pTab->apChange[iHash];
- pTab->apChange[iHash] = pChange;
+ pC->nRecord = nByte;
+ pC->op = op;
+ pC->pNext = pTab->apChange[iHash];
+ pTab->apChange[iHash] = pC;
}else if( pC->bIndirect ){
/* If the existing change is considered "indirect", but this current
@@ -209518,8 +219504,14 @@ static void sessionPreupdateOneChange(
pC->bIndirect = 0;
}
}
+
+ assert( rc==SQLITE_OK );
+ if( pSession->bEnableSize ){
+ rc = sessionUpdateMaxSize(op, pSession, pTab, pC);
+ }
}
+
/* If an error has occurred, mark the session object as failed. */
error_out:
if( pTab->bStat1 ){
@@ -209552,7 +219544,11 @@ static int sessionFindTable(
){
rc = sqlcipher_sqlite3session_attach(pSession, zName);
if( rc==SQLITE_OK ){
- for(pRet=pSession->pTable; pRet->pNext; pRet=pRet->pNext);
+ pRet = pSession->pTable;
+ while( ALWAYS(pRet) && pRet->pNext ){
+ pRet = pRet->pNext;
+ }
+ assert( pRet!=0 );
assert( 0==sqlcipher_sqlite3_strnicmp(pRet->zName, zName, nName+1) );
}
}
@@ -209849,7 +219845,7 @@ SQLITE_API int sqlcipher_sqlite3session_diff(
int nCol; /* Columns in zFrom.zTbl */
u8 *abPK;
const char **azCol = 0;
- rc = sessionTableInfo(db, zFrom, zTbl, &nCol, 0, &azCol, &abPK);
+ rc = sessionTableInfo(0, db, zFrom, zTbl, &nCol, 0, &azCol, &abPK);
if( rc==SQLITE_OK ){
if( pTo->nCol!=nCol ){
bMismatch = 1;
@@ -209947,7 +219943,7 @@ SQLITE_API int sqlcipher_sqlite3session_create(
** Free the list of table objects passed as the first argument. The contents
** of the changed-rows hash tables are also deleted.
*/
-static void sessionDeleteTable(SessionTable *pList){
+static void sessionDeleteTable(sqlcipher_sqlite3_session *pSession, SessionTable *pList){
SessionTable *pNext;
SessionTable *pTab;
@@ -209959,12 +219955,12 @@ static void sessionDeleteTable(SessionTable *pList){
SessionChange *pNextChange;
for(p=pTab->apChange[i]; p; p=pNextChange){
pNextChange = p->pNext;
- sqlcipher_sqlite3_free(p);
+ sessionFree(pSession, p);
}
}
- sqlcipher_sqlite3_free((char*)pTab->azCol); /* cast works around VC++ bug */
- sqlcipher_sqlite3_free(pTab->apChange);
- sqlcipher_sqlite3_free(pTab);
+ sessionFree(pSession, (char*)pTab->azCol); /* cast works around VC++ bug */
+ sessionFree(pSession, pTab->apChange);
+ sessionFree(pSession, pTab);
}
}
@@ -209992,9 +219988,11 @@ SQLITE_API void sqlcipher_sqlite3session_delete(sqlcipher_sqlite3_session *pSess
/* Delete all attached table objects. And the contents of their
** associated hash-tables. */
- sessionDeleteTable(pSession->pTable);
+ sessionDeleteTable(pSession, pSession->pTable);
- /* Free the session object itself. */
+ /* Assert that all allocations have been freed and then free the
+ ** session object itself. */
+ assert( pSession->nMalloc==0 );
sqlcipher_sqlite3_free(pSession);
}
@@ -210041,7 +220039,8 @@ SQLITE_API int sqlcipher_sqlite3session_attach(
if( !pTab ){
/* Allocate new SessionTable object. */
- pTab = (SessionTable *)sqlcipher_sqlite3_malloc64(sizeof(SessionTable) + nName + 1);
+ int nByte = sizeof(SessionTable) + nName + 1;
+ pTab = (SessionTable*)sessionMalloc64(pSession, nByte);
if( !pTab ){
rc = SQLITE_NOMEM;
}else{
@@ -210071,13 +220070,29 @@ SQLITE_API int sqlcipher_sqlite3session_attach(
** If successful, return zero. Otherwise, if an OOM condition is encountered,
** set *pRc to SQLITE_NOMEM and return non-zero.
*/
-static int sessionBufferGrow(SessionBuffer *p, size_t nByte, int *pRc){
- if( *pRc==SQLITE_OK && (size_t)(p->nAlloc-p->nBuf)<nByte ){
+static int sessionBufferGrow(SessionBuffer *p, i64 nByte, int *pRc){
+#define SESSION_MAX_BUFFER_SZ (0x7FFFFF00 - 1)
+ i64 nReq = p->nBuf + nByte;
+ if( *pRc==SQLITE_OK && nReq>p->nAlloc ){
u8 *aNew;
i64 nNew = p->nAlloc ? p->nAlloc : 128;
+
do {
nNew = nNew*2;
- }while( (size_t)(nNew-p->nBuf)<nByte );
+ }while( nNew<nReq );
+
+ /* The value of SESSION_MAX_BUFFER_SZ is copied from the implementation
+ ** of sqlcipher_sqlite3_realloc64(). Allocations greater than this size in bytes
+ ** always fail. It is used here to ensure that this routine can always
+ ** allocate up to this limit - instead of up to the largest power of
+ ** two smaller than the limit. */
+ if( nNew>SESSION_MAX_BUFFER_SZ ){
+ nNew = SESSION_MAX_BUFFER_SZ;
+ if( nNew<nReq ){
+ *pRc = SQLITE_NOMEM;
+ return 1;
+ }
+ }
aNew = (u8 *)sqlcipher_sqlite3_realloc64(p->aBuf, nNew);
if( 0==aNew ){
@@ -210306,6 +220321,7 @@ static int sessionAppendUpdate(
int i; /* Used to iterate through columns */
u8 *pCsr = p->aRecord; /* Used to iterate through old.* values */
+ assert( abPK!=0 );
sessionAppendByte(pBuf, SQLITE_UPDATE, &rc);
sessionAppendByte(pBuf, p->bIndirect, &rc);
for(i=0; i<sqlcipher_sqlite3_column_count(pStmt); i++){
@@ -210610,12 +220626,14 @@ static int sessionGenerateChangeset(
SessionBuffer buf = {0,0,0}; /* Buffer in which to accumlate changeset */
int rc; /* Return code */
- assert( xOutput==0 || (pnChangeset==0 && ppChangeset==0 ) );
+ assert( xOutput==0 || (pnChangeset==0 && ppChangeset==0) );
+ assert( xOutput!=0 || (pnChangeset!=0 && ppChangeset!=0) );
/* Zero the output variables in case an error occurs. If this session
** object is already in the error state (sqlcipher_sqlite3_session.rc != SQLITE_OK),
** this call will be a no-op. */
if( xOutput==0 ){
+ assert( pnChangeset!=0 && ppChangeset!=0 );
*pnChangeset = 0;
*ppChangeset = 0;
}
@@ -210629,8 +220647,8 @@ static int sessionGenerateChangeset(
for(pTab=pSession->pTable; rc==SQLITE_OK && pTab; pTab=pTab->pNext){
if( pTab->nEntry ){
const char *zName = pTab->zName;
- int nCol; /* Number of columns in table */
- u8 *abPK; /* Primary key array */
+ int nCol = 0; /* Number of columns in table */
+ u8 *abPK = 0; /* Primary key array */
const char **azCol = 0; /* Table columns */
int i; /* Used to iterate through hash buckets */
sqlcipher_sqlite3_stmt *pSel = 0; /* SELECT statement to query table pTab */
@@ -210638,7 +220656,7 @@ static int sessionGenerateChangeset(
int nNoop; /* Size of buffer after writing tbl header */
/* Check the table schema is still Ok. */
- rc = sessionTableInfo(db, pSession->zDb, zName, &nCol, 0, &azCol, &abPK);
+ rc = sessionTableInfo(0, db, pSession->zDb, zName, &nCol, 0,&azCol,&abPK);
if( !rc && (pTab->nCol!=nCol || memcmp(abPK, pTab->abPK, nCol)) ){
rc = SQLITE_SCHEMA;
}
@@ -210668,6 +220686,7 @@ static int sessionGenerateChangeset(
sessionAppendCol(&buf, pSel, iCol, &rc);
}
}else{
+ assert( abPK!=0 ); /* Because sessionSelectStmt() returned ok */
rc = sessionAppendUpdate(&buf, bPatchset, pSel, p, abPK);
}
}else if( p->op!=SQLITE_INSERT ){
@@ -210728,7 +220747,14 @@ SQLITE_API int sqlcipher_sqlite3session_changeset(
int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */
void **ppChangeset /* OUT: Buffer containing changeset */
){
- return sessionGenerateChangeset(pSession, 0, 0, 0, pnChangeset, ppChangeset);
+ int rc;
+
+ if( pnChangeset==0 || ppChangeset==0 ) return SQLITE_MISUSE;
+ rc = sessionGenerateChangeset(pSession, 0, 0, 0, pnChangeset,ppChangeset);
+ assert( rc || pnChangeset==0
+ || pSession->bEnableSize==0 || *pnChangeset<=pSession->nMaxChangesetSize
+ );
+ return rc;
}
/*
@@ -210739,6 +220765,7 @@ SQLITE_API int sqlcipher_sqlite3session_changeset_strm(
int (*xOutput)(void *pOut, const void *pData, int nData),
void *pOut
){
+ if( xOutput==0 ) return SQLITE_MISUSE;
return sessionGenerateChangeset(pSession, 0, xOutput, pOut, 0, 0);
}
@@ -210750,6 +220777,7 @@ SQLITE_API int sqlcipher_sqlite3session_patchset_strm(
int (*xOutput)(void *pOut, const void *pData, int nData),
void *pOut
){
+ if( xOutput==0 ) return SQLITE_MISUSE;
return sessionGenerateChangeset(pSession, 1, xOutput, pOut, 0, 0);
}
@@ -210765,6 +220793,7 @@ SQLITE_API int sqlcipher_sqlite3session_patchset(
int *pnPatchset, /* OUT: Size of buffer at *ppChangeset */
void **ppPatchset /* OUT: Buffer containing changeset */
){
+ if( pnPatchset==0 || ppPatchset==0 ) return SQLITE_MISUSE;
return sessionGenerateChangeset(pSession, 1, 0, 0, pnPatchset, ppPatchset);
}
@@ -210814,6 +220843,46 @@ SQLITE_API int sqlcipher_sqlite3session_isempty(sqlcipher_sqlite3_session *pSess
}
/*
+** Return the amount of heap memory in use.
+*/
+SQLITE_API sqlcipher_sqlite3_int64 sqlcipher_sqlite3session_memory_used(sqlcipher_sqlite3_session *pSession){
+ return pSession->nMalloc;
+}
+
+/*
+** Configure the session object passed as the first argument.
+*/
+SQLITE_API int sqlcipher_sqlite3session_object_config(sqlcipher_sqlite3_session *pSession, int op, void *pArg){
+ int rc = SQLITE_OK;
+ switch( op ){
+ case SQLITE_SESSION_OBJCONFIG_SIZE: {
+ int iArg = *(int*)pArg;
+ if( iArg>=0 ){
+ if( pSession->pTable ){
+ rc = SQLITE_MISUSE;
+ }else{
+ pSession->bEnableSize = (iArg!=0);
+ }
+ }
+ *(int*)pArg = pSession->bEnableSize;
+ break;
+ }
+
+ default:
+ rc = SQLITE_MISUSE;
+ }
+
+ return rc;
+}
+
+/*
+** Return the maximum size of sqlcipher_sqlite3session_changeset() output.
+*/
+SQLITE_API sqlcipher_sqlite3_int64 sqlcipher_sqlite3session_changeset_size(sqlcipher_sqlite3_session *pSession){
+ return pSession->nMaxChangesetSize;
+}
+
+/*
** Do the work for either sqlcipher_sqlite3changeset_start() or start_strm().
*/
static int sessionChangesetStart(
@@ -210822,7 +220891,8 @@ static int sessionChangesetStart(
void *pIn,
int nChangeset, /* Size of buffer pChangeset in bytes */
void *pChangeset, /* Pointer to buffer containing changeset */
- int bInvert /* True to invert changeset */
+ int bInvert, /* True to invert changeset */
+ int bSkipEmpty /* True to skip empty UPDATE changes */
){
sqlcipher_sqlite3_changeset_iter *pRet; /* Iterator to return */
int nByte; /* Number of bytes to allocate for iterator */
@@ -210843,6 +220913,7 @@ static int sessionChangesetStart(
pRet->in.pIn = pIn;
pRet->in.bEof = (xInput ? 0 : 1);
pRet->bInvert = bInvert;
+ pRet->bSkipEmpty = bSkipEmpty;
/* Populate the output variable and return success. */
*pp = pRet;
@@ -210857,7 +220928,7 @@ SQLITE_API int sqlcipher_sqlite3changeset_start(
int nChangeset, /* Size of buffer pChangeset in bytes */
void *pChangeset /* Pointer to buffer containing changeset */
){
- return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset, 0);
+ return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset, 0, 0);
}
SQLITE_API int sqlcipher_sqlite3changeset_start_v2(
sqlcipher_sqlite3_changeset_iter **pp, /* OUT: Changeset iterator handle */
@@ -210866,7 +220937,7 @@ SQLITE_API int sqlcipher_sqlite3changeset_start_v2(
int flags
){
int bInvert = !!(flags & SQLITE_CHANGESETSTART_INVERT);
- return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset, bInvert);
+ return sessionChangesetStart(pp, 0, 0, nChangeset, pChangeset, bInvert, 0);
}
/*
@@ -210877,7 +220948,7 @@ SQLITE_API int sqlcipher_sqlite3changeset_start_strm(
int (*xInput)(void *pIn, void *pData, int *pnData),
void *pIn
){
- return sessionChangesetStart(pp, xInput, pIn, 0, 0, 0);
+ return sessionChangesetStart(pp, xInput, pIn, 0, 0, 0, 0);
}
SQLITE_API int sqlcipher_sqlite3changeset_start_v2_strm(
sqlcipher_sqlite3_changeset_iter **pp, /* OUT: Changeset iterator handle */
@@ -210886,7 +220957,7 @@ SQLITE_API int sqlcipher_sqlite3changeset_start_v2_strm(
int flags
){
int bInvert = !!(flags & SQLITE_CHANGESETSTART_INVERT);
- return sessionChangesetStart(pp, xInput, pIn, 0, 0, bInvert);
+ return sessionChangesetStart(pp, xInput, pIn, 0, 0, bInvert, 0);
}
/*
@@ -211012,11 +221083,14 @@ static int sessionReadRecord(
SessionInput *pIn, /* Input data */
int nCol, /* Number of values in record */
u8 *abPK, /* Array of primary key flags, or NULL */
- sqlcipher_sqlite3_value **apOut /* Write values to this array */
+ sqlcipher_sqlite3_value **apOut, /* Write values to this array */
+ int *pbEmpty
){
int i; /* Used to iterate through columns */
int rc = SQLITE_OK;
+ assert( pbEmpty==0 || *pbEmpty==0 );
+ if( pbEmpty ) *pbEmpty = 1;
for(i=0; i<nCol && rc==SQLITE_OK; i++){
int eType = 0; /* Type of value (SQLITE_NULL, TEXT etc.) */
if( abPK && abPK[i]==0 ) continue;
@@ -211028,6 +221102,7 @@ static int sessionReadRecord(
eType = pIn->aData[pIn->iNext++];
assert( apOut[i]==0 );
if( eType ){
+ if( pbEmpty ) *pbEmpty = 0;
apOut[i] = sqlcipher_sqlite3ValueNew(0);
if( !apOut[i] ) rc = SQLITE_NOMEM;
}
@@ -211207,31 +221282,27 @@ static int sessionChangesetReadTblhdr(sqlcipher_sqlite3_changeset_iter *p){
}
/*
-** Advance the changeset iterator to the next change.
+** Advance the changeset iterator to the next change. The differences between
+** this function and sessionChangesetNext() are that
**
-** If both paRec and pnRec are NULL, then this function works like the public
-** API sqlcipher_sqlite3changeset_next(). If SQLITE_ROW is returned, then the
-** sqlcipher_sqlite3changeset_new() and old() APIs may be used to query for values.
-**
-** Otherwise, if paRec and pnRec are not NULL, then a pointer to the change
-** record is written to *paRec before returning and the number of bytes in
-** the record to *pnRec.
+** * If pbEmpty is not NULL and the change is a no-op UPDATE (an UPDATE
+** that modifies no columns), this function sets (*pbEmpty) to 1.
**
-** Either way, this function returns SQLITE_ROW if the iterator is
-** successfully advanced to the next change in the changeset, an SQLite
-** error code if an error occurs, or SQLITE_DONE if there are no further
-** changes in the changeset.
+** * If the iterator is configured to skip no-op UPDATEs,
+** sessionChangesetNext() does that. This function does not.
*/
-static int sessionChangesetNext(
+static int sessionChangesetNextOne(
sqlcipher_sqlite3_changeset_iter *p, /* Changeset iterator */
u8 **paRec, /* If non-NULL, store record pointer here */
int *pnRec, /* If non-NULL, store size of record here */
- int *pbNew /* If non-NULL, true if new table */
+ int *pbNew, /* If non-NULL, true if new table */
+ int *pbEmpty
){
int i;
u8 op;
assert( (paRec==0 && pnRec==0) || (paRec && pnRec) );
+ assert( pbEmpty==0 || *pbEmpty==0 );
/* If the iterator is in the error-state, return immediately. */
if( p->rc!=SQLITE_OK ) return p->rc;
@@ -211304,13 +221375,13 @@ static int sessionChangesetNext(
/* If this is an UPDATE or DELETE, read the old.* record. */
if( p->op!=SQLITE_INSERT && (p->bPatchset==0 || p->op==SQLITE_DELETE) ){
u8 *abPK = p->bPatchset ? p->abPK : 0;
- p->rc = sessionReadRecord(&p->in, p->nCol, abPK, apOld);
+ p->rc = sessionReadRecord(&p->in, p->nCol, abPK, apOld, 0);
if( p->rc!=SQLITE_OK ) return p->rc;
}
/* If this is an INSERT or UPDATE, read the new.* record. */
if( p->op!=SQLITE_DELETE ){
- p->rc = sessionReadRecord(&p->in, p->nCol, 0, apNew);
+ p->rc = sessionReadRecord(&p->in, p->nCol, 0, apNew, pbEmpty);
if( p->rc!=SQLITE_OK ) return p->rc;
}
@@ -211338,6 +221409,37 @@ static int sessionChangesetNext(
}
/*
+** Advance the changeset iterator to the next change.
+**
+** If both paRec and pnRec are NULL, then this function works like the public
+** API sqlcipher_sqlite3changeset_next(). If SQLITE_ROW is returned, then the
+** sqlcipher_sqlite3changeset_new() and old() APIs may be used to query for values.
+**
+** Otherwise, if paRec and pnRec are not NULL, then a pointer to the change
+** record is written to *paRec before returning and the number of bytes in
+** the record to *pnRec.
+**
+** Either way, this function returns SQLITE_ROW if the iterator is
+** successfully advanced to the next change in the changeset, an SQLite
+** error code if an error occurs, or SQLITE_DONE if there are no further
+** changes in the changeset.
+*/
+static int sessionChangesetNext(
+ sqlcipher_sqlite3_changeset_iter *p, /* Changeset iterator */
+ u8 **paRec, /* If non-NULL, store record pointer here */
+ int *pnRec, /* If non-NULL, store size of record here */
+ int *pbNew /* If non-NULL, true if new table */
+){
+ int bEmpty;
+ int rc;
+ do {
+ bEmpty = 0;
+ rc = sessionChangesetNextOne(p, paRec, pnRec, pbNew, &bEmpty);
+ }while( rc==SQLITE_ROW && p->bSkipEmpty && bEmpty);
+ return rc;
+}
+
+/*
** Advance an iterator created by sqlcipher_sqlite3changeset_start() to the next
** change in the changeset. This function may return SQLITE_ROW, SQLITE_DONE
** or SQLITE_CORRUPT.
@@ -211609,9 +221711,9 @@ static int sessionChangesetInvert(
/* Read the old.* and new.* records for the update change. */
pInput->iNext += 2;
- rc = sessionReadRecord(pInput, nCol, 0, &apVal[0]);
+ rc = sessionReadRecord(pInput, nCol, 0, &apVal[0], 0);
if( rc==SQLITE_OK ){
- rc = sessionReadRecord(pInput, nCol, 0, &apVal[nCol]);
+ rc = sessionReadRecord(pInput, nCol, 0, &apVal[nCol], 0);
}
/* Write the new old.* record. Consists of the PK columns from the
@@ -211655,11 +221757,11 @@ static int sessionChangesetInvert(
}
assert( rc==SQLITE_OK );
- if( pnInverted ){
+ if( pnInverted && ALWAYS(ppInverted) ){
*pnInverted = sOut.nBuf;
*ppInverted = sOut.aBuf;
sOut.aBuf = 0;
- }else if( sOut.nBuf>0 ){
+ }else if( sOut.nBuf>0 && ALWAYS(xOutput!=0) ){
rc = xOutput(pOut, sOut.aBuf, sOut.nBuf);
}
@@ -211712,16 +221814,25 @@ SQLITE_API int sqlcipher_sqlite3changeset_invert_strm(
return rc;
}
+
+typedef struct SessionUpdate SessionUpdate;
+struct SessionUpdate {
+ sqlcipher_sqlite3_stmt *pStmt;
+ u32 *aMask;
+ SessionUpdate *pNext;
+};
+
typedef struct SessionApplyCtx SessionApplyCtx;
struct SessionApplyCtx {
sqlcipher_sqlite3 *db;
sqlcipher_sqlite3_stmt *pDelete; /* DELETE statement */
- sqlcipher_sqlite3_stmt *pUpdate; /* UPDATE statement */
sqlcipher_sqlite3_stmt *pInsert; /* INSERT statement */
sqlcipher_sqlite3_stmt *pSelect; /* SELECT statement */
int nCol; /* Size of azCol[] and abPK[] arrays */
const char **azCol; /* Array of column names */
u8 *abPK; /* Boolean array - true if column is in PK */
+ u32 *aUpdateMask; /* Used by sessionUpdateFind */
+ SessionUpdate *pUp;
int bStat1; /* True if table is sqlite_stat1 */
int bDeferConstraints; /* True to defer constraints */
int bInvertConstraints; /* Invert when iterating constraints buffer */
@@ -211731,6 +221842,167 @@ struct SessionApplyCtx {
u8 bRebase; /* True to collect rebase information */
};
+/* Number of prepared UPDATE statements to cache. */
+#define SESSION_UPDATE_CACHE_SZ 12
+
+/*
+** Find a prepared UPDATE statement suitable for the UPDATE step currently
+** being visited by the iterator. The UPDATE is of the form:
+**
+** UPDATE tbl SET col = ?, col2 = ? WHERE pk1 IS ? AND pk2 IS ?
+*/
+static int sessionUpdateFind(
+ sqlcipher_sqlite3_changeset_iter *pIter,
+ SessionApplyCtx *p,
+ int bPatchset,
+ sqlcipher_sqlite3_stmt **ppStmt
+){
+ int rc = SQLITE_OK;
+ SessionUpdate *pUp = 0;
+ int nCol = pIter->nCol;
+ int nU32 = (pIter->nCol+33)/32;
+ int ii;
+
+ if( p->aUpdateMask==0 ){
+ p->aUpdateMask = sqlcipher_sqlite3_malloc(nU32*sizeof(u32));
+ if( p->aUpdateMask==0 ){
+ rc = SQLITE_NOMEM;
+ }
+ }
+
+ if( rc==SQLITE_OK ){
+ memset(p->aUpdateMask, 0, nU32*sizeof(u32));
+ rc = SQLITE_CORRUPT;
+ for(ii=0; ii<pIter->nCol; ii++){
+ if( sessionChangesetNew(pIter, ii) ){
+ p->aUpdateMask[ii/32] |= (1<<(ii%32));
+ rc = SQLITE_OK;
+ }
+ }
+ }
+
+ if( rc==SQLITE_OK ){
+ if( bPatchset ) p->aUpdateMask[nCol/32] |= (1<<(nCol%32));
+
+ if( p->pUp ){
+ int nUp = 0;
+ SessionUpdate **pp = &p->pUp;
+ while( 1 ){
+ nUp++;
+ if( 0==memcmp(p->aUpdateMask, (*pp)->aMask, nU32*sizeof(u32)) ){
+ pUp = *pp;
+ *pp = pUp->pNext;
+ pUp->pNext = p->pUp;
+ p->pUp = pUp;
+ break;
+ }
+
+ if( (*pp)->pNext ){
+ pp = &(*pp)->pNext;
+ }else{
+ if( nUp>=SESSION_UPDATE_CACHE_SZ ){
+ sqlcipher_sqlite3_finalize((*pp)->pStmt);
+ sqlcipher_sqlite3_free(*pp);
+ *pp = 0;
+ }
+ break;
+ }
+ }
+ }
+
+ if( pUp==0 ){
+ int nByte = sizeof(SessionUpdate) * nU32*sizeof(u32);
+ int bStat1 = (sqlcipher_sqlite3_stricmp(pIter->zTab, "sqlite_stat1")==0);
+ pUp = (SessionUpdate*)sqlcipher_sqlite3_malloc(nByte);
+ if( pUp==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ const char *zSep = "";
+ SessionBuffer buf;
+
+ memset(&buf, 0, sizeof(buf));
+ pUp->aMask = (u32*)&pUp[1];
+ memcpy(pUp->aMask, p->aUpdateMask, nU32*sizeof(u32));
+
+ sessionAppendStr(&buf, "UPDATE main.", &rc);
+ sessionAppendIdent(&buf, pIter->zTab, &rc);
+ sessionAppendStr(&buf, " SET ", &rc);
+
+ /* Create the assignments part of the UPDATE */
+ for(ii=0; ii<pIter->nCol; ii++){
+ if( p->abPK[ii]==0 && sessionChangesetNew(pIter, ii) ){
+ sessionAppendStr(&buf, zSep, &rc);
+ sessionAppendIdent(&buf, p->azCol[ii], &rc);
+ sessionAppendStr(&buf, " = ?", &rc);
+ sessionAppendInteger(&buf, ii*2+1, &rc);
+ zSep = ", ";
+ }
+ }
+
+ /* Create the WHERE clause part of the UPDATE */
+ zSep = "";
+ sessionAppendStr(&buf, " WHERE ", &rc);
+ for(ii=0; ii<pIter->nCol; ii++){
+ if( p->abPK[ii] || (bPatchset==0 && sessionChangesetOld(pIter, ii)) ){
+ sessionAppendStr(&buf, zSep, &rc);
+ if( bStat1 && ii==1 ){
+ assert( sqlcipher_sqlite3_stricmp(p->azCol[ii], "idx")==0 );
+ sessionAppendStr(&buf,
+ "idx IS CASE "
+ "WHEN length(?4)=0 AND typeof(?4)='blob' THEN NULL "
+ "ELSE ?4 END ", &rc
+ );
+ }else{
+ sessionAppendIdent(&buf, p->azCol[ii], &rc);
+ sessionAppendStr(&buf, " IS ?", &rc);
+ sessionAppendInteger(&buf, ii*2+2, &rc);
+ }
+ zSep = " AND ";
+ }
+ }
+
+ if( rc==SQLITE_OK ){
+ char *zSql = (char*)buf.aBuf;
+ rc = sqlcipher_sqlite3_prepare_v2(p->db, zSql, buf.nBuf, &pUp->pStmt, 0);
+ }
+
+ if( rc!=SQLITE_OK ){
+ sqlcipher_sqlite3_free(pUp);
+ pUp = 0;
+ }else{
+ pUp->pNext = p->pUp;
+ p->pUp = pUp;
+ }
+ sqlcipher_sqlite3_free(buf.aBuf);
+ }
+ }
+ }
+
+ assert( (rc==SQLITE_OK)==(pUp!=0) );
+ if( pUp ){
+ *ppStmt = pUp->pStmt;
+ }else{
+ *ppStmt = 0;
+ }
+ return rc;
+}
+
+/*
+** Free all cached UPDATE statements.
+*/
+static void sessionUpdateFree(SessionApplyCtx *p){
+ SessionUpdate *pUp;
+ SessionUpdate *pNext;
+ for(pUp=p->pUp; pUp; pUp=pNext){
+ pNext = pUp->pNext;
+ sqlcipher_sqlite3_finalize(pUp->pStmt);
+ sqlcipher_sqlite3_free(pUp);
+ }
+ p->pUp = 0;
+ sqlcipher_sqlite3_free(p->aUpdateMask);
+ p->aUpdateMask = 0;
+}
+
/*
** Formulate a statement to DELETE a row from database db. Assuming a table
** structure like this:
@@ -211801,103 +222073,6 @@ static int sessionDeleteRow(
}
/*
-** Formulate and prepare a statement to UPDATE a row from database db.
-** Assuming a table structure like this:
-**
-** CREATE TABLE x(a, b, c, d, PRIMARY KEY(a, c));
-**
-** The UPDATE statement looks like this:
-**
-** UPDATE x SET
-** a = CASE WHEN ?2 THEN ?3 ELSE a END,
-** b = CASE WHEN ?5 THEN ?6 ELSE b END,
-** c = CASE WHEN ?8 THEN ?9 ELSE c END,
-** d = CASE WHEN ?11 THEN ?12 ELSE d END
-** WHERE a = ?1 AND c = ?7 AND (?13 OR
-** (?5==0 OR b IS ?4) AND (?11==0 OR d IS ?10) AND
-** )
-**
-** For each column in the table, there are three variables to bind:
-**
-** ?(i*3+1) The old.* value of the column, if any.
-** ?(i*3+2) A boolean flag indicating that the value is being modified.
-** ?(i*3+3) The new.* value of the column, if any.
-**
-** Also, a boolean flag that, if set to true, causes the statement to update
-** a row even if the non-PK values do not match. This is required if the
-** conflict-handler is invoked with CHANGESET_DATA and returns
-** CHANGESET_REPLACE. This is variable "?(nCol*3+1)".
-**
-** If successful, SQLITE_OK is returned and SessionApplyCtx.pUpdate is left
-** pointing to the prepared version of the SQL statement.
-*/
-static int sessionUpdateRow(
- sqlcipher_sqlite3 *db, /* Database handle */
- const char *zTab, /* Table name */
- SessionApplyCtx *p /* Session changeset-apply context */
-){
- int rc = SQLITE_OK;
- int i;
- const char *zSep = "";
- SessionBuffer buf = {0, 0, 0};
-
- /* Append "UPDATE tbl SET " */
- sessionAppendStr(&buf, "UPDATE main.", &rc);
- sessionAppendIdent(&buf, zTab, &rc);
- sessionAppendStr(&buf, " SET ", &rc);
-
- /* Append the assignments */
- for(i=0; i<p->nCol; i++){
- sessionAppendStr(&buf, zSep, &rc);
- sessionAppendIdent(&buf, p->azCol[i], &rc);
- sessionAppendStr(&buf, " = CASE WHEN ?", &rc);
- sessionAppendInteger(&buf, i*3+2, &rc);
- sessionAppendStr(&buf, " THEN ?", &rc);
- sessionAppendInteger(&buf, i*3+3, &rc);
- sessionAppendStr(&buf, " ELSE ", &rc);
- sessionAppendIdent(&buf, p->azCol[i], &rc);
- sessionAppendStr(&buf, " END", &rc);
- zSep = ", ";
- }
-
- /* Append the PK part of the WHERE clause */
- sessionAppendStr(&buf, " WHERE ", &rc);
- for(i=0; i<p->nCol; i++){
- if( p->abPK[i] ){
- sessionAppendIdent(&buf, p->azCol[i], &rc);
- sessionAppendStr(&buf, " = ?", &rc);
- sessionAppendInteger(&buf, i*3+1, &rc);
- sessionAppendStr(&buf, " AND ", &rc);
- }
- }
-
- /* Append the non-PK part of the WHERE clause */
- sessionAppendStr(&buf, " (?", &rc);
- sessionAppendInteger(&buf, p->nCol*3+1, &rc);
- sessionAppendStr(&buf, " OR 1", &rc);
- for(i=0; i<p->nCol; i++){
- if( !p->abPK[i] ){
- sessionAppendStr(&buf, " AND (?", &rc);
- sessionAppendInteger(&buf, i*3+2, &rc);
- sessionAppendStr(&buf, "=0 OR ", &rc);
- sessionAppendIdent(&buf, p->azCol[i], &rc);
- sessionAppendStr(&buf, " IS ?", &rc);
- sessionAppendInteger(&buf, i*3+1, &rc);
- sessionAppendStr(&buf, ")", &rc);
- }
- }
- sessionAppendStr(&buf, ")", &rc);
-
- if( rc==SQLITE_OK ){
- rc = sqlcipher_sqlite3_prepare_v2(db, (char *)buf.aBuf, buf.nBuf, &p->pUpdate, 0);
- }
- sqlcipher_sqlite3_free(buf.aBuf);
-
- return rc;
-}
-
-
-/*
** Formulate and prepare an SQL statement to query table zTab by primary
** key. Assuming the following table structure:
**
@@ -211978,17 +222153,6 @@ static int sessionStat1Sql(sqlcipher_sqlite3 *db, SessionApplyCtx *p){
);
}
if( rc==SQLITE_OK ){
- rc = sessionPrepare(db, &p->pUpdate,
- "UPDATE main.sqlite_stat1 SET "
- "tbl = CASE WHEN ?2 THEN ?3 ELSE tbl END, "
- "idx = CASE WHEN ?5 THEN ?6 ELSE idx END, "
- "stat = CASE WHEN ?8 THEN ?9 ELSE stat END "
- "WHERE tbl=?1 AND idx IS "
- "CASE WHEN length(?4)=0 AND typeof(?4)='blob' THEN NULL ELSE ?4 END "
- "AND (?10 OR ?8=0 OR stat IS ?7)"
- );
- }
- if( rc==SQLITE_OK ){
rc = sessionPrepare(db, &p->pDelete,
"DELETE FROM main.sqlite_stat1 WHERE tbl=?1 AND idx IS "
"CASE WHEN length(?2)=0 AND typeof(?2)='blob' THEN NULL ELSE ?2 END "
@@ -212053,7 +222217,7 @@ static int sessionBindRow(
for(i=0; rc==SQLITE_OK && i<nCol; i++){
if( !abPK || abPK[i] ){
- sqlcipher_sqlite3_value *pVal;
+ sqlcipher_sqlite3_value *pVal = 0;
(void)xValue(pIter, i, &pVal);
if( pVal==0 ){
/* The value in the changeset was "undefined". This indicates a
@@ -212304,7 +222468,7 @@ static int sessionApplyOneOp(
int nCol;
int rc = SQLITE_OK;
- assert( p->pDelete && p->pUpdate && p->pInsert && p->pSelect );
+ assert( p->pDelete && p->pInsert && p->pSelect );
assert( p->azCol && p->abPK );
assert( !pbReplace || *pbReplace==0 );
@@ -212344,29 +222508,28 @@ static int sessionApplyOneOp(
}else if( op==SQLITE_UPDATE ){
int i;
+ sqlcipher_sqlite3_stmt *pUp = 0;
+ int bPatchset = (pbRetry==0 || pIter->bPatchset);
+
+ rc = sessionUpdateFind(pIter, p, bPatchset, &pUp);
/* Bind values to the UPDATE statement. */
for(i=0; rc==SQLITE_OK && i<nCol; i++){
sqlcipher_sqlite3_value *pOld = sessionChangesetOld(pIter, i);
sqlcipher_sqlite3_value *pNew = sessionChangesetNew(pIter, i);
-
- sqlcipher_sqlite3_bind_int(p->pUpdate, i*3+2, !!pNew);
- if( pOld ){
- rc = sessionBindValue(p->pUpdate, i*3+1, pOld);
+ if( p->abPK[i] || (bPatchset==0 && pOld) ){
+ rc = sessionBindValue(pUp, i*2+2, pOld);
}
if( rc==SQLITE_OK && pNew ){
- rc = sessionBindValue(p->pUpdate, i*3+3, pNew);
+ rc = sessionBindValue(pUp, i*2+1, pNew);
}
}
- if( rc==SQLITE_OK ){
- sqlcipher_sqlite3_bind_int(p->pUpdate, nCol*3+1, pbRetry==0 || pIter->bPatchset);
- }
if( rc!=SQLITE_OK ) return rc;
/* Attempt the UPDATE. In the case of a NOTFOUND or DATA conflict,
** the result will be SQLITE_OK with 0 rows modified. */
- sqlcipher_sqlite3_step(p->pUpdate);
- rc = sqlcipher_sqlite3_reset(p->pUpdate);
+ sqlcipher_sqlite3_step(pUp);
+ rc = sqlcipher_sqlite3_reset(pUp);
if( rc==SQLITE_OK && sqlcipher_sqlite3_changes(p->db)==0 ){
/* A NOTFOUND or DATA error. Search the table to see if it contains
@@ -212498,7 +222661,7 @@ static int sessionRetryConstraints(
memset(&pApply->constraints, 0, sizeof(SessionBuffer));
rc = sessionChangesetStart(
- &pIter2, 0, 0, cons.nBuf, cons.aBuf, pApply->bInvertConstraints
+ &pIter2, 0, 0, cons.nBuf, cons.aBuf, pApply->bInvertConstraints, 1
);
if( rc==SQLITE_OK ){
size_t nByte = 2*pApply->nCol*sizeof(sqlcipher_sqlite3_value*);
@@ -212589,14 +222752,13 @@ static int sessionChangesetApply(
);
if( rc!=SQLITE_OK ) break;
+ sessionUpdateFree(&sApply);
sqlcipher_sqlite3_free((char*)sApply.azCol); /* cast works around VC++ bug */
sqlcipher_sqlite3_finalize(sApply.pDelete);
- sqlcipher_sqlite3_finalize(sApply.pUpdate);
sqlcipher_sqlite3_finalize(sApply.pInsert);
sqlcipher_sqlite3_finalize(sApply.pSelect);
sApply.db = db;
sApply.pDelete = 0;
- sApply.pUpdate = 0;
sApply.pInsert = 0;
sApply.pSelect = 0;
sApply.nCol = 0;
@@ -212624,7 +222786,7 @@ static int sessionChangesetApply(
int i;
sqlcipher_sqlite3changeset_pk(pIter, &abPK, 0);
- rc = sessionTableInfo(
+ rc = sessionTableInfo(0,
db, "main", zNew, &sApply.nCol, &zTab, &sApply.azCol, &sApply.abPK
);
if( rc!=SQLITE_OK ) break;
@@ -212660,11 +222822,10 @@ static int sessionChangesetApply(
}
sApply.bStat1 = 1;
}else{
- if((rc = sessionSelectRow(db, zTab, &sApply))
- || (rc = sessionUpdateRow(db, zTab, &sApply))
- || (rc = sessionDeleteRow(db, zTab, &sApply))
- || (rc = sessionInsertRow(db, zTab, &sApply))
- ){
+ if( (rc = sessionSelectRow(db, zTab, &sApply))
+ || (rc = sessionDeleteRow(db, zTab, &sApply))
+ || (rc = sessionInsertRow(db, zTab, &sApply))
+ ){
break;
}
sApply.bStat1 = 0;
@@ -212723,9 +222884,9 @@ static int sessionChangesetApply(
*pnRebase = sApply.rebase.nBuf;
sApply.rebase.aBuf = 0;
}
+ sessionUpdateFree(&sApply);
sqlcipher_sqlite3_finalize(sApply.pInsert);
sqlcipher_sqlite3_finalize(sApply.pDelete);
- sqlcipher_sqlite3_finalize(sApply.pUpdate);
sqlcipher_sqlite3_finalize(sApply.pSelect);
sqlcipher_sqlite3_free((char*)sApply.azCol); /* cast works around VC++ bug */
sqlcipher_sqlite3_free((char*)sApply.constraints.aBuf);
@@ -212756,8 +222917,8 @@ SQLITE_API int sqlcipher_sqlite3changeset_apply_v2(
int flags
){
sqlcipher_sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */
- int bInverse = !!(flags & SQLITE_CHANGESETAPPLY_INVERT);
- int rc = sessionChangesetStart(&pIter, 0, 0, nChangeset, pChangeset,bInverse);
+ int bInv = !!(flags & SQLITE_CHANGESETAPPLY_INVERT);
+ int rc = sessionChangesetStart(&pIter, 0, 0, nChangeset, pChangeset, bInv, 1);
if( rc==SQLITE_OK ){
rc = sessionChangesetApply(
db, pIter, xFilter, xConflict, pCtx, ppRebase, pnRebase, flags
@@ -212815,7 +222976,7 @@ SQLITE_API int sqlcipher_sqlite3changeset_apply_v2_strm(
){
sqlcipher_sqlite3_changeset_iter *pIter; /* Iterator to skip through changeset */
int bInverse = !!(flags & SQLITE_CHANGESETAPPLY_INVERT);
- int rc = sessionChangesetStart(&pIter, xInput, pIn, 0, 0, bInverse);
+ int rc = sessionChangesetStart(&pIter, xInput, pIn, 0, 0, bInverse, 1);
if( rc==SQLITE_OK ){
rc = sessionChangesetApply(
db, pIter, xFilter, xConflict, pCtx, ppRebase, pnRebase, flags
@@ -213103,7 +223264,7 @@ static int sessionChangesetToHash(
}
}
- if( sessionGrowHash(pIter->bPatchset, pTab) ){
+ if( sessionGrowHash(0, pIter->bPatchset, pTab) ){
rc = SQLITE_NOMEM;
break;
}
@@ -213199,9 +223360,9 @@ static int sessionChangegroupOutput(
if( rc==SQLITE_OK ){
if( xOutput ){
if( buf.nBuf>0 ) rc = xOutput(pOut, buf.aBuf, buf.nBuf);
- }else{
+ }else if( ppOut ){
*ppOut = buf.aBuf;
- *pnOut = buf.nBuf;
+ if( pnOut ) *pnOut = buf.nBuf;
buf.aBuf = 0;
}
}
@@ -213289,7 +223450,7 @@ SQLITE_API int sqlcipher_sqlite3changegroup_output_strm(
*/
SQLITE_API void sqlcipher_sqlite3changegroup_delete(sqlcipher_sqlite3_changegroup *pGrp){
if( pGrp ){
- sessionDeleteTable(pGrp->pList);
+ sessionDeleteTable(0, pGrp->pList);
sqlcipher_sqlite3_free(pGrp);
}
}
@@ -213435,7 +223596,7 @@ static void sessionAppendPartialUpdate(
int n1 = sessionSerialLen(a1);
int n2 = sessionSerialLen(a2);
if( pIter->abPK[i] || a2[0]==0 ){
- if( !pIter->abPK[i] ) bData = 1;
+ if( !pIter->abPK[i] && a1[0] ) bData = 1;
memcpy(pOut, a1, n1);
pOut += n1;
}else if( a2[0]!=0xFF ){
@@ -213601,7 +223762,7 @@ static int sessionRebase(
if( sOut.nBuf>0 ){
rc = xOutput(pOut, sOut.aBuf, sOut.nBuf);
}
- }else{
+ }else if( ppOut ){
*ppOut = (void*)sOut.aBuf;
*pnOut = sOut.nBuf;
sOut.aBuf = 0;
@@ -213690,7 +223851,7 @@ SQLITE_API int sqlcipher_sqlite3rebaser_rebase_strm(
*/
SQLITE_API void sqlcipher_sqlite3rebaser_delete(sqlcipher_sqlite3_rebaser *p){
if( p ){
- sessionDeleteTable(p->grp.pList);
+ sessionDeleteTable(0, p->grp.pList);
sqlcipher_sqlite3_free(p);
}
}
@@ -214344,8 +224505,20 @@ typedef sqlcipher_sqlite3_uint64 u64;
#endif
#define testcase(x)
-#define ALWAYS(x) 1
-#define NEVER(x) 0
+
+#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
+# define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1
+#endif
+#if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS)
+# 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
#define MIN(x,y) (((x) < (y)) ? (x) : (y))
#define MAX(x,y) (((x) > (y)) ? (x) : (y))
@@ -214405,7 +224578,7 @@ SQLITE_API extern int sqlcipher_sqlite3_fts5_may_be_corrupt;
** A version of memcmp() that does not cause asan errors if one of the pointer
** parameters is NULL and the number of bytes to compare is zero.
*/
-#define fts5Memcmp(s1, s2, n) ((n)==0 ? 0 : memcmp((s1), (s2), (n)))
+#define fts5Memcmp(s1, s2, n) ((n)<=0 ? 0 : memcmp((s1), (s2), (n)))
/* Mark a function parameter as unused, to suppress nuisance compiler
** warnings. */
@@ -214744,6 +224917,9 @@ static void sqlcipher_sqlite3Fts5IndexCloseReader(Fts5Index*);
*/
static const char *sqlcipher_sqlite3Fts5IterTerm(Fts5IndexIter*, int*);
static int sqlcipher_sqlite3Fts5IterNextScan(Fts5IndexIter*);
+static void *sqlcipher_sqlite3Fts5StructureRef(Fts5Index*);
+static void sqlcipher_sqlite3Fts5StructureRelease(void*);
+static int sqlcipher_sqlite3Fts5StructureTest(Fts5Index*, void*);
/*
@@ -215521,9 +225697,9 @@ struct fts5yyParser {
};
typedef struct fts5yyParser fts5yyParser;
+/* #include <assert.h> */
#ifndef NDEBUG
/* #include <stdio.h> */
-/* #include <assert.h> */
static FILE *fts5yyTraceFILE = 0;
static char *fts5yyTracePrompt = 0;
#endif /* NDEBUG */
@@ -216152,55 +226328,6 @@ static fts5YYACTIONTYPE fts5yy_reduce(
(void)fts5yyLookahead;
(void)fts5yyLookaheadToken;
fts5yymsp = fts5yypParser->fts5yytos;
- assert( fts5yyruleno<(int)(sizeof(fts5yyRuleName)/sizeof(fts5yyRuleName[0])) );
-#ifndef NDEBUG
- if( fts5yyTraceFILE ){
- fts5yysize = fts5yyRuleInfoNRhs[fts5yyruleno];
- if( fts5yysize ){
- fprintf(fts5yyTraceFILE, "%sReduce %d [%s]%s, pop back to state %d.\n",
- fts5yyTracePrompt,
- fts5yyruleno, fts5yyRuleName[fts5yyruleno],
- fts5yyruleno<fts5YYNRULE_WITH_ACTION ? "" : " without external action",
- fts5yymsp[fts5yysize].stateno);
- }else{
- fprintf(fts5yyTraceFILE, "%sReduce %d [%s]%s.\n",
- fts5yyTracePrompt, fts5yyruleno, fts5yyRuleName[fts5yyruleno],
- fts5yyruleno<fts5YYNRULE_WITH_ACTION ? "" : " without external action");
- }
- }
-#endif /* NDEBUG */
-
- /* Check that the stack is large enough to grow by a single entry
- ** if the RHS of the rule is empty. This ensures that there is room
- ** enough on the stack to push the LHS value */
- if( fts5yyRuleInfoNRhs[fts5yyruleno]==0 ){
-#ifdef fts5YYTRACKMAXSTACKDEPTH
- if( (int)(fts5yypParser->fts5yytos - fts5yypParser->fts5yystack)>fts5yypParser->fts5yyhwm ){
- fts5yypParser->fts5yyhwm++;
- assert( fts5yypParser->fts5yyhwm == (int)(fts5yypParser->fts5yytos - fts5yypParser->fts5yystack));
- }
-#endif
-#if fts5YYSTACKDEPTH>0
- if( fts5yypParser->fts5yytos>=fts5yypParser->fts5yystackEnd ){
- fts5yyStackOverflow(fts5yypParser);
- /* The call to fts5yyStackOverflow() above pops the stack until it is
- ** empty, causing the main parser loop to exit. So the return value
- ** is never used and does not matter. */
- return 0;
- }
-#else
- if( fts5yypParser->fts5yytos>=&fts5yypParser->fts5yystack[fts5yypParser->fts5yystksz-1] ){
- if( fts5yyGrowStack(fts5yypParser) ){
- fts5yyStackOverflow(fts5yypParser);
- /* The call to fts5yyStackOverflow() above pops the stack until it is
- ** empty, causing the main parser loop to exit. So the return value
- ** is never used and does not matter. */
- return 0;
- }
- fts5yymsp = fts5yypParser->fts5yytos;
- }
-#endif
- }
switch( fts5yyruleno ){
/* Beginning here are the reduction cases. A typical example
@@ -216503,12 +226630,56 @@ static void sqlcipher_sqlite3Fts5Parser(
}
#endif
- do{
+ while(1){ /* Exit by "break" */
+ assert( fts5yypParser->fts5yytos>=fts5yypParser->fts5yystack );
assert( fts5yyact==fts5yypParser->fts5yytos->stateno );
fts5yyact = fts5yy_find_shift_action((fts5YYCODETYPE)fts5yymajor,fts5yyact);
if( fts5yyact >= fts5YY_MIN_REDUCE ){
- fts5yyact = fts5yy_reduce(fts5yypParser,fts5yyact-fts5YY_MIN_REDUCE,fts5yymajor,
- fts5yyminor sqlcipher_sqlite3Fts5ParserCTX_PARAM);
+ unsigned int fts5yyruleno = fts5yyact - fts5YY_MIN_REDUCE; /* Reduce by this rule */
+#ifndef NDEBUG
+ assert( fts5yyruleno<(int)(sizeof(fts5yyRuleName)/sizeof(fts5yyRuleName[0])) );
+ if( fts5yyTraceFILE ){
+ int fts5yysize = fts5yyRuleInfoNRhs[fts5yyruleno];
+ if( fts5yysize ){
+ fprintf(fts5yyTraceFILE, "%sReduce %d [%s]%s, pop back to state %d.\n",
+ fts5yyTracePrompt,
+ fts5yyruleno, fts5yyRuleName[fts5yyruleno],
+ fts5yyruleno<fts5YYNRULE_WITH_ACTION ? "" : " without external action",
+ fts5yypParser->fts5yytos[fts5yysize].stateno);
+ }else{
+ fprintf(fts5yyTraceFILE, "%sReduce %d [%s]%s.\n",
+ fts5yyTracePrompt, fts5yyruleno, fts5yyRuleName[fts5yyruleno],
+ fts5yyruleno<fts5YYNRULE_WITH_ACTION ? "" : " without external action");
+ }
+ }
+#endif /* NDEBUG */
+
+ /* Check that the stack is large enough to grow by a single entry
+ ** if the RHS of the rule is empty. This ensures that there is room
+ ** enough on the stack to push the LHS value */
+ if( fts5yyRuleInfoNRhs[fts5yyruleno]==0 ){
+#ifdef fts5YYTRACKMAXSTACKDEPTH
+ if( (int)(fts5yypParser->fts5yytos - fts5yypParser->fts5yystack)>fts5yypParser->fts5yyhwm ){
+ fts5yypParser->fts5yyhwm++;
+ assert( fts5yypParser->fts5yyhwm ==
+ (int)(fts5yypParser->fts5yytos - fts5yypParser->fts5yystack));
+ }
+#endif
+#if fts5YYSTACKDEPTH>0
+ if( fts5yypParser->fts5yytos>=fts5yypParser->fts5yystackEnd ){
+ fts5yyStackOverflow(fts5yypParser);
+ break;
+ }
+#else
+ if( fts5yypParser->fts5yytos>=&fts5yypParser->fts5yystack[fts5yypParser->fts5yystksz-1] ){
+ if( fts5yyGrowStack(fts5yypParser) ){
+ fts5yyStackOverflow(fts5yypParser);
+ break;
+ }
+ }
+#endif
+ }
+ fts5yyact = fts5yy_reduce(fts5yypParser,fts5yyruleno,fts5yymajor,fts5yyminor sqlcipher_sqlite3Fts5ParserCTX_PARAM);
}else if( fts5yyact <= fts5YY_MAX_SHIFTREDUCE ){
fts5yy_shift(fts5yypParser,fts5yyact,(fts5YYCODETYPE)fts5yymajor,fts5yyminor);
#ifndef fts5YYNOERRORRECOVERY
@@ -216564,14 +226735,13 @@ static void sqlcipher_sqlite3Fts5Parser(
fts5yy_destructor(fts5yypParser, (fts5YYCODETYPE)fts5yymajor, &fts5yyminorunion);
fts5yymajor = fts5YYNOCODE;
}else{
- while( fts5yypParser->fts5yytos >= fts5yypParser->fts5yystack
- && (fts5yyact = fts5yy_find_reduce_action(
- fts5yypParser->fts5yytos->stateno,
- fts5YYERRORSYMBOL)) > fts5YY_MAX_SHIFTREDUCE
- ){
+ while( fts5yypParser->fts5yytos > fts5yypParser->fts5yystack ){
+ fts5yyact = fts5yy_find_reduce_action(fts5yypParser->fts5yytos->stateno,
+ fts5YYERRORSYMBOL);
+ if( fts5yyact<=fts5YY_MAX_SHIFTREDUCE ) break;
fts5yy_pop_parser_stack(fts5yypParser);
}
- if( fts5yypParser->fts5yytos < fts5yypParser->fts5yystack || fts5yymajor==0 ){
+ if( fts5yypParser->fts5yytos <= fts5yypParser->fts5yystack || fts5yymajor==0 ){
fts5yy_destructor(fts5yypParser,(fts5YYCODETYPE)fts5yymajor,&fts5yyminorunion);
fts5yy_parse_failed(fts5yypParser);
#ifndef fts5YYNOERRORRECOVERY
@@ -216621,7 +226791,7 @@ static void sqlcipher_sqlite3Fts5Parser(
break;
#endif
}
- }while( fts5yypParser->fts5yytos>fts5yypParser->fts5yystack );
+ }
#ifndef NDEBUG
if( fts5yyTraceFILE ){
fts5yyStackEntry *i;
@@ -217434,7 +227604,6 @@ static void sqlcipher_sqlite3Fts5BufferAppendBlob(
u32 nData,
const u8 *pData
){
- assert_nc( *pRc || nData>=0 );
if( nData ){
if( fts5BufferGrow(pRc, pBuf, nData) ) return;
memcpy(&pBuf->p[pBuf->n], pData, nData);
@@ -217544,7 +227713,7 @@ static int sqlcipher_sqlite3Fts5PoslistNext64(
return 1;
}else{
i64 iOff = *piOff;
- int iVal;
+ u32 iVal;
fts5FastGetVarint32(a, i, iVal);
if( iVal<=1 ){
if( iVal==0 ){
@@ -217553,15 +227722,19 @@ static int sqlcipher_sqlite3Fts5PoslistNext64(
}
fts5FastGetVarint32(a, i, iVal);
iOff = ((i64)iVal) << 32;
+ assert( iOff>=0 );
fts5FastGetVarint32(a, i, iVal);
if( iVal<2 ){
/* This is a corrupt record. So stop parsing it here. */
*piOff = -1;
return 1;
}
+ *piOff = iOff + ((iVal-2) & 0x7FFFFFFF);
+ }else{
+ *piOff = (iOff & (i64)0x7FFFFFFF<<32)+((iOff + (iVal-2)) & 0x7FFFFFFF);
}
- *piOff = iOff + ((iVal-2) & 0x7FFFFFFF);
*pi = i;
+ assert_nc( *piOff>=iOff );
return 0;
}
}
@@ -217600,14 +227773,16 @@ static void sqlcipher_sqlite3Fts5PoslistSafeAppend(
i64 *piPrev,
i64 iPos
){
- static const i64 colmask = ((i64)(0x7FFFFFFF)) << 32;
- if( (iPos & colmask) != (*piPrev & colmask) ){
- pBuf->p[pBuf->n++] = 1;
- pBuf->n += sqlcipher_sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos>>32));
- *piPrev = (iPos & colmask);
+ if( iPos>=*piPrev ){
+ static const i64 colmask = ((i64)(0x7FFFFFFF)) << 32;
+ if( (iPos & colmask) != (*piPrev & colmask) ){
+ pBuf->p[pBuf->n++] = 1;
+ pBuf->n += sqlcipher_sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos>>32));
+ *piPrev = (iPos & colmask);
+ }
+ pBuf->n += sqlcipher_sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos-*piPrev)+2);
+ *piPrev = iPos;
}
- pBuf->n += sqlcipher_sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], (iPos-*piPrev)+2);
- *piPrev = iPos;
}
static int sqlcipher_sqlite3Fts5PoslistWriterAppend(
@@ -218309,7 +228484,7 @@ static int sqlcipher_sqlite3Fts5ConfigParse(
nByte = nArg * (sizeof(char*) + sizeof(u8));
pRet->azCol = (char**)sqlcipher_sqlite3Fts5MallocZero(&rc, nByte);
- pRet->abUnindexed = (u8*)&pRet->azCol[nArg];
+ pRet->abUnindexed = pRet->azCol ? (u8*)&pRet->azCol[nArg] : 0;
pRet->zDb = sqlcipher_sqlite3Fts5Strndup(&rc, azArg[1], -1);
pRet->zName = sqlcipher_sqlite3Fts5Strndup(&rc, azArg[2], -1);
pRet->bColumnsize = 1;
@@ -218334,6 +228509,7 @@ static int sqlcipher_sqlite3Fts5ConfigParse(
z = fts5ConfigSkipWhitespace(z);
if( z && *z=='=' ){
bOption = 1;
+ assert( zOne!=0 );
z++;
if( bMustBeCol ) z = 0;
}
@@ -218350,7 +228526,11 @@ static int sqlcipher_sqlite3Fts5ConfigParse(
rc = SQLITE_ERROR;
}else{
if( bOption ){
- rc = fts5ConfigParseSpecial(pGlobal, pRet, zOne, zTwo?zTwo:"", pzErr);
+ rc = fts5ConfigParseSpecial(pGlobal, pRet,
+ ALWAYS(zOne)?zOne:"",
+ zTwo?zTwo:"",
+ pzErr
+ );
}else{
rc = fts5ConfigParseColumn(pRet, zOne, zTwo, pzErr);
zOne = 0;
@@ -218868,6 +229048,7 @@ static void sqlcipher_sqlite3Fts5ParseError(Fts5Parse *pParse, const char *zFmt,
va_list ap;
va_start(ap, zFmt);
if( pParse->rc==SQLITE_OK ){
+ assert( pParse->zErr==0 );
pParse->zErr = sqlcipher_sqlite3_vmprintf(zFmt, ap);
pParse->rc = SQLITE_ERROR;
}
@@ -219166,6 +229347,7 @@ static i64 fts5ExprSynonymRowid(Fts5ExprTerm *pTerm, int bDesc, int *pbEof){
int bRetValid = 0;
Fts5ExprTerm *p;
+ assert( pTerm );
assert( pTerm->pSynonym );
assert( bDesc==0 || bDesc==1 );
for(p=pTerm; p; p=p->pSynonym){
@@ -220233,8 +230415,8 @@ static int sqlcipher_sqlite3Fts5ExprFirst(Fts5Expr *p, Fts5Index *pIdx, i64 iFir
}
/* If the iterator is not at a real match, skip forward until it is. */
- while( pRoot->bNomatch ){
- assert( pRoot->bEof==0 && rc==SQLITE_OK );
+ while( pRoot->bNomatch && rc==SQLITE_OK ){
+ assert( pRoot->bEof==0 );
rc = fts5ExprNodeNext(p, pRoot, 0, 0);
}
return rc;
@@ -220358,6 +230540,9 @@ static Fts5ExprNearset *sqlcipher_sqlite3Fts5ParseNearset(
}else{
if( pRet->nPhrase>0 ){
Fts5ExprPhrase *pLast = pRet->apPhrase[pRet->nPhrase-1];
+ assert( pParse!=0 );
+ assert( pParse->apPhrase!=0 );
+ assert( pParse->nPhrase>=2 );
assert( pLast==pParse->apPhrase[pParse->nPhrase-2] );
if( pPhrase->nTerm==0 ){
fts5ExprPhraseFree(pPhrase);
@@ -220606,7 +230791,7 @@ static int sqlcipher_sqlite3Fts5ExprClonePhrase(
sCtx.pPhrase = sqlcipher_sqlite3Fts5MallocZero(&rc, sizeof(Fts5ExprPhrase));
}
- if( rc==SQLITE_OK ){
+ if( rc==SQLITE_OK && ALWAYS(sCtx.pPhrase) ){
/* All the allocations succeeded. Put the expression object together. */
pNew->pIndex = pExpr->pIndex;
pNew->pConfig = pExpr->pConfig;
@@ -220877,9 +231062,8 @@ static void sqlcipher_sqlite3Fts5ParseSetColset(
){
Fts5Colset *pFree = pColset;
if( pParse->pConfig->eDetail==FTS5_DETAIL_NONE ){
- pParse->rc = SQLITE_ERROR;
- pParse->zErr = sqlcipher_sqlite3_mprintf(
- "fts5: column queries are not supported (detail=none)"
+ sqlcipher_sqlite3Fts5ParseError(pParse,
+ "fts5: column queries are not supported (detail=none)"
);
}else{
fts5ParseSetColset(pParse, pExpr, pColset, &pFree);
@@ -221053,13 +231237,10 @@ static Fts5ExprNode *sqlcipher_sqlite3Fts5ParseNode(
|| pPhrase->nTerm>1
|| (pPhrase->nTerm>0 && pPhrase->aTerm[0].bFirst)
){
- assert( pParse->rc==SQLITE_OK );
- pParse->rc = SQLITE_ERROR;
- assert( pParse->zErr==0 );
- pParse->zErr = sqlcipher_sqlite3_mprintf(
+ sqlcipher_sqlite3Fts5ParseError(pParse,
"fts5: %s queries are not supported (detail!=full)",
pNear->nPhrase==1 ? "phrase": "NEAR"
- );
+ );
sqlcipher_sqlite3_free(pRet);
pRet = 0;
}
@@ -221145,6 +231326,7 @@ static Fts5ExprNode *sqlcipher_sqlite3Fts5ParseImplicitAnd(
return pRet;
}
+#ifdef SQLITE_TEST
static char *fts5ExprTermPrint(Fts5ExprTerm *pTerm){
sqlcipher_sqlite3_int64 nByte = 0;
Fts5ExprTerm *p;
@@ -221511,12 +231693,14 @@ static void fts5ExprFold(
sqlcipher_sqlite3_result_int(pCtx, sqlcipher_sqlite3Fts5UnicodeFold(iCode, bRemoveDiacritics));
}
}
+#endif /* ifdef SQLITE_TEST */
/*
** This is called during initialization to register the fts5_expr() scalar
** UDF with the SQLite handle passed as the only argument.
*/
static int sqlcipher_sqlite3Fts5ExprInit(Fts5Global *pGlobal, sqlcipher_sqlite3 *db){
+#ifdef SQLITE_TEST
struct Fts5ExprFunc {
const char *z;
void (*x)(sqlcipher_sqlite3_context*,int,sqlcipher_sqlite3_value**);
@@ -221534,6 +231718,10 @@ static int sqlcipher_sqlite3Fts5ExprInit(Fts5Global *pGlobal, sqlcipher_sqlite3
struct Fts5ExprFunc *p = &aFunc[i];
rc = sqlcipher_sqlite3_create_function(db, p->z, -1, SQLITE_UTF8, pCtx, p->x, 0, 0);
}
+#else
+ int rc = SQLITE_OK;
+ UNUSED_PARAM2(pGlobal,db);
+#endif
/* Avoid warnings indicating that sqlcipher_sqlite3Fts5ParserTrace() and
** sqlcipher_sqlite3Fts5ParserFallback() are unused */
@@ -221584,6 +231772,15 @@ struct Fts5PoslistPopulator {
int bMiss;
};
+/*
+** Clear the position lists associated with all phrases in the expression
+** passed as the first argument. Argument bLive is true if the expression
+** might be pointing to a real entry, otherwise it has just been reset.
+**
+** At present this function is only used for detail=col and detail=none
+** fts5 tables. This implies that all phrases must be at most 1 token
+** in size, as phrase matches are not supported without detail=full.
+*/
static Fts5PoslistPopulator *sqlcipher_sqlite3Fts5ExprClearPoslists(Fts5Expr *pExpr, int bLive){
Fts5PoslistPopulator *pRet;
pRet = sqlcipher_sqlite3_malloc64(sizeof(Fts5PoslistPopulator)*pExpr->nPhrase);
@@ -221593,7 +231790,7 @@ static Fts5PoslistPopulator *sqlcipher_sqlite3Fts5ExprClearPoslists(Fts5Expr *pE
for(i=0; i<pExpr->nPhrase; i++){
Fts5Buffer *pBuf = &pExpr->apExprPhrase[i]->poslist;
Fts5ExprNode *pNode = pExpr->apExprPhrase[i]->pNode;
- assert( pExpr->apExprPhrase[i]->nTerm==1 );
+ assert( pExpr->apExprPhrase[i]->nTerm<=1 );
if( bLive &&
(pBuf->n==0 || pNode->iRowid!=pExpr->pRoot->iRowid || pNode->bEof)
){
@@ -222144,7 +232341,7 @@ static int sqlcipher_sqlite3Fts5HashWrite(
p->bContent = 1;
}else{
/* Append a new column value, if necessary */
- assert( iCol>=p->iCol );
+ assert_nc( iCol>=p->iCol );
if( iCol!=p->iCol ){
if( pHash->eDetail==FTS5_DETAIL_FULL ){
pPtr[p->nData++] = 0x01;
@@ -222645,7 +232842,7 @@ struct Fts5Index {
sqlcipher_sqlite3_stmt *pWriter; /* "INSERT ... %_data VALUES(?,?)" */
sqlcipher_sqlite3_stmt *pDeleter; /* "DELETE FROM %_data ... id>=? AND id<=?" */
sqlcipher_sqlite3_stmt *pIdxWriter; /* "INSERT ... %_idx VALUES(?,?,?,?)" */
- sqlcipher_sqlite3_stmt *pIdxDeleter; /* "DELETE FROM %_idx WHERE segid=? */
+ sqlcipher_sqlite3_stmt *pIdxDeleter; /* "DELETE FROM %_idx WHERE segid=?" */
sqlcipher_sqlite3_stmt *pIdxSelect;
int nRead; /* Total number of blocks read */
@@ -222780,7 +232977,7 @@ struct Fts5SegIter {
int iLeafPgno; /* Current leaf page number */
Fts5Data *pLeaf; /* Current leaf data */
Fts5Data *pNextLeaf; /* Leaf page (iLeafPgno+1) */
- int iLeafOffset; /* Byte offset within current leaf */
+ i64 iLeafOffset; /* Byte offset within current leaf */
/* Next method */
void (*xNext)(Fts5Index*, Fts5SegIter*, int*);
@@ -222949,8 +233146,11 @@ static int fts5BufferCompareBlob(
** res = *pLeft - *pRight
*/
static int fts5BufferCompare(Fts5Buffer *pLeft, Fts5Buffer *pRight){
- int nCmp = MIN(pLeft->n, pRight->n);
- int res = fts5Memcmp(pLeft->p, pRight->p, nCmp);
+ int nCmp, res;
+ nCmp = MIN(pLeft->n, pRight->n);
+ assert( nCmp<=0 || pLeft->p!=0 );
+ assert( nCmp<=0 || pRight->p!=0 );
+ res = fts5Memcmp(pLeft->p, pRight->p, nCmp);
return (res==0 ? (pLeft->n - pRight->n) : res);
}
@@ -223046,6 +233246,7 @@ static Fts5Data *fts5DataRead(Fts5Index *p, i64 iRowid){
return pRet;
}
+
/*
** Release a reference to data record returned by an earlier call to
** fts5DataRead().
@@ -223170,6 +233371,58 @@ static void fts5StructureRef(Fts5Structure *pStruct){
pStruct->nRef++;
}
+static void *sqlcipher_sqlite3Fts5StructureRef(Fts5Index *p){
+ fts5StructureRef(p->pStruct);
+ return (void*)p->pStruct;
+}
+static void sqlcipher_sqlite3Fts5StructureRelease(void *p){
+ if( p ){
+ fts5StructureRelease((Fts5Structure*)p);
+ }
+}
+static int sqlcipher_sqlite3Fts5StructureTest(Fts5Index *p, void *pStruct){
+ if( p->pStruct!=(Fts5Structure*)pStruct ){
+ return SQLITE_ABORT;
+ }
+ return SQLITE_OK;
+}
+
+/*
+** Ensure that structure object (*pp) is writable.
+**
+** This function is a no-op if (*pRc) is not SQLITE_OK when it is called. If
+** an error occurs, (*pRc) is set to an SQLite error code before returning.
+*/
+static void fts5StructureMakeWritable(int *pRc, Fts5Structure **pp){
+ Fts5Structure *p = *pp;
+ if( *pRc==SQLITE_OK && p->nRef>1 ){
+ i64 nByte = sizeof(Fts5Structure)+(p->nLevel-1)*sizeof(Fts5StructureLevel);
+ Fts5Structure *pNew;
+ pNew = (Fts5Structure*)sqlcipher_sqlite3Fts5MallocZero(pRc, nByte);
+ if( pNew ){
+ int i;
+ memcpy(pNew, p, nByte);
+ for(i=0; i<p->nLevel; i++) pNew->aLevel[i].aSeg = 0;
+ for(i=0; i<p->nLevel; i++){
+ Fts5StructureLevel *pLvl = &pNew->aLevel[i];
+ nByte = sizeof(Fts5StructureSegment) * pNew->aLevel[i].nSeg;
+ pLvl->aSeg = (Fts5StructureSegment*)sqlcipher_sqlite3Fts5MallocZero(pRc, nByte);
+ if( pLvl->aSeg==0 ){
+ for(i=0; i<p->nLevel; i++){
+ sqlcipher_sqlite3_free(pNew->aLevel[i].aSeg);
+ }
+ sqlcipher_sqlite3_free(pNew);
+ return;
+ }
+ memcpy(pLvl->aSeg, p->aLevel[i].aSeg, nByte);
+ }
+ p->nRef--;
+ pNew->nRef = 1;
+ }
+ *pp = pNew;
+ }
+}
+
/*
** Deserialize and return the structure record currently stored in serialized
** form within buffer pData/nData.
@@ -223271,9 +233524,11 @@ static int fts5StructureDecode(
}
/*
-**
+** Add a level to the Fts5Structure.aLevel[] array of structure object
+** (*ppStruct).
*/
static void fts5StructureAddLevel(int *pRc, Fts5Structure **ppStruct){
+ fts5StructureMakeWritable(pRc, ppStruct);
if( *pRc==SQLITE_OK ){
Fts5Structure *pStruct = *ppStruct;
int nLevel = pStruct->nLevel;
@@ -223960,7 +234215,7 @@ static void fts5SegIterLoadNPos(Fts5Index *p, Fts5SegIter *pIter){
static void fts5SegIterLoadRowid(Fts5Index *p, Fts5SegIter *pIter){
u8 *a = pIter->pLeaf->p; /* Buffer to read data from */
- int iOff = pIter->iLeafOffset;
+ i64 iOff = pIter->iLeafOffset;
ASSERT_SZLEAF_OK(pIter->pLeaf);
if( iOff>=pIter->pLeaf->szLeaf ){
@@ -223993,7 +234248,7 @@ static void fts5SegIterLoadRowid(Fts5Index *p, Fts5SegIter *pIter){
*/
static void fts5SegIterLoadTerm(Fts5Index *p, Fts5SegIter *pIter, int nKeep){
u8 *a = pIter->pLeaf->p; /* Buffer to read data from */
- int iOff = pIter->iLeafOffset; /* Offset to read at */
+ i64 iOff = pIter->iLeafOffset; /* Offset to read at */
int nNew; /* Bytes of new data */
iOff += fts5GetVarint32(&a[iOff], nNew);
@@ -224067,6 +234322,7 @@ static void fts5SegIterInit(
if( p->rc==SQLITE_OK ){
pIter->iLeafOffset = 4;
+ assert( pIter->pLeaf!=0 );
assert_nc( pIter->pLeaf->nn>4 );
assert_nc( fts5LeafFirstTermOff(pIter->pLeaf)==4 );
pIter->iPgidxOff = pIter->pLeaf->szLeaf+1;
@@ -224169,8 +234425,12 @@ static void fts5SegIterReverseNewPage(Fts5Index *p, Fts5SegIter *pIter){
int iRowidOff;
iRowidOff = fts5LeafFirstRowidOff(pNew);
if( iRowidOff ){
- pIter->pLeaf = pNew;
- pIter->iLeafOffset = iRowidOff;
+ if( iRowidOff>=pNew->szLeaf ){
+ p->rc = FTS5_CORRUPT;
+ }else{
+ pIter->pLeaf = pNew;
+ pIter->iLeafOffset = iRowidOff;
+ }
}
}
@@ -224419,14 +234679,9 @@ static void fts5SegIterNext(
}else{
/* The following could be done by calling fts5SegIterLoadNPos(). But
** this block is particularly performance critical, so equivalent
- ** code is inlined.
- **
- ** Later: Switched back to fts5SegIterLoadNPos() because it supports
- ** detail=none mode. Not ideal.
- */
+ ** code is inlined. */
int nSz;
- assert( p->rc==SQLITE_OK );
- assert( pIter->iLeafOffset<=pIter->pLeaf->nn );
+ assert_nc( pIter->iLeafOffset<=pIter->pLeaf->nn );
fts5FastGetVarint32(pIter->pLeaf->p, pIter->iLeafOffset, nSz);
pIter->bDel = (nSz & 0x0001);
pIter->nPos = nSz>>1;
@@ -224455,7 +234710,7 @@ static void fts5SegIterReverse(Fts5Index *p, Fts5SegIter *pIter){
if( pDlidx ){
int iSegid = pIter->pSeg->iSegid;
pgnoLast = fts5DlidxIterPgno(pDlidx);
- pLast = fts5DataRead(p, FTS5_SEGMENT_ROWID(iSegid, pgnoLast));
+ pLast = fts5LeafRead(p, FTS5_SEGMENT_ROWID(iSegid, pgnoLast));
}else{
Fts5Data *pLeaf = pIter->pLeaf; /* Current leaf data */
@@ -224482,7 +234737,7 @@ static void fts5SegIterReverse(Fts5Index *p, Fts5SegIter *pIter){
** forward to find the page containing the last rowid. */
for(pgno=pIter->iLeafPgno+1; !p->rc && pgno<=pSeg->pgnoLast; pgno++){
i64 iAbs = FTS5_SEGMENT_ROWID(pSeg->iSegid, pgno);
- Fts5Data *pNew = fts5DataRead(p, iAbs);
+ Fts5Data *pNew = fts5LeafRead(p, iAbs);
if( pNew ){
int iRowid, bTermless;
iRowid = fts5LeafFirstRowidOff(pNew);
@@ -224513,6 +234768,10 @@ static void fts5SegIterReverse(Fts5Index *p, Fts5SegIter *pIter){
pIter->pLeaf = pLast;
pIter->iLeafPgno = pgnoLast;
iOff = fts5LeafFirstRowidOff(pLast);
+ if( iOff>pLast->szLeaf ){
+ p->rc = FTS5_CORRUPT;
+ return;
+ }
iOff += fts5GetVarint(&pLast->p[iOff], (u64*)&pIter->iRowid);
pIter->iLeafOffset = iOff;
@@ -224521,7 +234780,6 @@ static void fts5SegIterReverse(Fts5Index *p, Fts5SegIter *pIter){
}else{
pIter->iEndofDoclist = fts5LeafFirstTermOff(pLast);
}
-
}
fts5SegIterReverseInitPage(p, pIter);
@@ -224573,21 +234831,20 @@ static void fts5LeafSeek(
Fts5SegIter *pIter, /* Iterator to seek */
const u8 *pTerm, int nTerm /* Term to search for */
){
- int iOff;
+ u32 iOff;
const u8 *a = pIter->pLeaf->p;
- int szLeaf = pIter->pLeaf->szLeaf;
- int n = pIter->pLeaf->nn;
+ u32 n = (u32)pIter->pLeaf->nn;
u32 nMatch = 0;
u32 nKeep = 0;
u32 nNew = 0;
u32 iTermOff;
- int iPgidx; /* Current offset in pgidx */
+ u32 iPgidx; /* Current offset in pgidx */
int bEndOfPage = 0;
assert( p->rc==SQLITE_OK );
- iPgidx = szLeaf;
+ iPgidx = (u32)pIter->pLeaf->szLeaf;
iPgidx += fts5GetVarint32(&a[iPgidx], iTermOff);
iOff = iTermOff;
if( iOff>n ){
@@ -224653,15 +234910,15 @@ static void fts5LeafSeek(
if( pIter->pLeaf==0 ) return;
a = pIter->pLeaf->p;
if( fts5LeafIsTermless(pIter->pLeaf)==0 ){
- iPgidx = pIter->pLeaf->szLeaf;
+ iPgidx = (u32)pIter->pLeaf->szLeaf;
iPgidx += fts5GetVarint32(&pIter->pLeaf->p[iPgidx], iOff);
- if( iOff<4 || iOff>=pIter->pLeaf->szLeaf ){
+ if( iOff<4 || (i64)iOff>=pIter->pLeaf->szLeaf ){
p->rc = FTS5_CORRUPT;
return;
}else{
nKeep = 0;
iTermOff = iOff;
- n = pIter->pLeaf->nn;
+ n = (u32)pIter->pLeaf->nn;
iOff += fts5GetVarint32(&a[iOff], nNew);
break;
}
@@ -225029,7 +235286,7 @@ static void fts5SegIterGotoPage(
fts5SegIterNextPage(p, pIter);
assert( p->rc!=SQLITE_OK || pIter->iLeafPgno==iLeafPgno );
- if( p->rc==SQLITE_OK ){
+ if( p->rc==SQLITE_OK && ALWAYS(pIter->pLeaf!=0) ){
int iOff;
u8 *a = pIter->pLeaf->p;
int n = pIter->pLeaf->szLeaf;
@@ -225418,7 +235675,7 @@ static void fts5ChunkIterate(
int pgno = pSeg->iLeafPgno;
int pgnoSave = 0;
- /* This function does notmwork with detail=none databases. */
+ /* This function does not work with detail=none databases. */
assert( p->pConfig->eDetail!=FTS5_DETAIL_NONE );
if( (pSeg->flags & FTS5_SEGITER_REVERSE)==0 ){
@@ -225431,6 +235688,9 @@ static void fts5ChunkIterate(
fts5DataRelease(pData);
if( nRem<=0 ){
break;
+ }else if( pSeg->pSeg==0 ){
+ p->rc = FTS5_CORRUPT;
+ return;
}else{
pgno++;
pData = fts5LeafRead(p, FTS5_SEGMENT_ROWID(pSeg->pSeg->iSegid, pgno));
@@ -225458,7 +235718,11 @@ static void fts5SegiterPoslist(
Fts5Colset *pColset,
Fts5Buffer *pBuf
){
+ assert( pBuf!=0 );
+ assert( pSeg!=0 );
if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos+FTS5_DATA_ZERO_PADDING) ){
+ assert( pBuf->p!=0 );
+ assert( pBuf->nSpace >= pBuf->n+pSeg->nPos+FTS5_DATA_ZERO_PADDING );
memset(&pBuf->p[pBuf->n+pSeg->nPos], 0, FTS5_DATA_ZERO_PADDING);
if( pColset==0 ){
fts5ChunkIterate(p, pSeg, (void*)pBuf, fts5PoslistCallback);
@@ -225482,66 +235746,72 @@ static void fts5SegiterPoslist(
}
/*
-** IN/OUT parameter (*pa) points to a position list n bytes in size. If
-** the position list contains entries for column iCol, then (*pa) is set
-** to point to the sub-position-list for that column and the number of
-** bytes in it returned. Or, if the argument position list does not
-** contain any entries for column iCol, return 0.
+** Parameter pPos points to a buffer containing a position list, size nPos.
+** This function filters it according to pColset (which must be non-NULL)
+** and sets pIter->base.pData/nData to point to the new position list.
+** If memory is required for the new position list, use buffer pIter->poslist.
+** Or, if the new position list is a contiguous subset of the input, set
+** pIter->base.pData/nData to point directly to it.
+**
+** This function is a no-op if *pRc is other than SQLITE_OK when it is
+** called. If an OOM error is encountered, *pRc is set to SQLITE_NOMEM
+** before returning.
*/
-static int fts5IndexExtractCol(
- const u8 **pa, /* IN/OUT: Pointer to poslist */
- int n, /* IN: Size of poslist in bytes */
- int iCol /* Column to extract from poslist */
-){
- int iCurrent = 0; /* Anything before the first 0x01 is col 0 */
- const u8 *p = *pa;
- const u8 *pEnd = &p[n]; /* One byte past end of position list */
-
- while( iCol>iCurrent ){
- /* Advance pointer p until it points to pEnd or an 0x01 byte that is
- ** not part of a varint. Note that it is not possible for a negative
- ** or extremely large varint to occur within an uncorrupted position
- ** list. So the last byte of each varint may be assumed to have a clear
- ** 0x80 bit. */
- while( *p!=0x01 ){
- while( *p++ & 0x80 );
- if( p>=pEnd ) return 0;
- }
- *pa = p++;
- iCurrent = *p++;
- if( iCurrent & 0x80 ){
- p--;
- p += fts5GetVarint32(p, iCurrent);
- }
- }
- if( iCol!=iCurrent ) return 0;
-
- /* Advance pointer p until it points to pEnd or an 0x01 byte that is
- ** not part of a varint */
- while( p<pEnd && *p!=0x01 ){
- while( *p++ & 0x80 );
- }
-
- return p - (*pa);
-}
-
static void fts5IndexExtractColset(
int *pRc,
Fts5Colset *pColset, /* Colset to filter on */
const u8 *pPos, int nPos, /* Position list */
- Fts5Buffer *pBuf /* Output buffer */
+ Fts5Iter *pIter
){
if( *pRc==SQLITE_OK ){
- int i;
- fts5BufferZero(pBuf);
- for(i=0; i<pColset->nCol; i++){
- const u8 *pSub = pPos;
- int nSub = fts5IndexExtractCol(&pSub, nPos, pColset->aiCol[i]);
- if( nSub ){
- fts5BufferAppendBlob(pRc, pBuf, nSub, pSub);
+ const u8 *p = pPos;
+ const u8 *aCopy = p;
+ const u8 *pEnd = &p[nPos]; /* One byte past end of position list */
+ int i = 0;
+ int iCurrent = 0;
+
+ if( pColset->nCol>1 && sqlcipher_sqlite3Fts5BufferSize(pRc, &pIter->poslist, nPos) ){
+ return;
+ }
+
+ while( 1 ){
+ while( pColset->aiCol[i]<iCurrent ){
+ i++;
+ if( i==pColset->nCol ){
+ pIter->base.pData = pIter->poslist.p;
+ pIter->base.nData = pIter->poslist.n;
+ return;
+ }
+ }
+
+ /* Advance pointer p until it points to pEnd or an 0x01 byte that is
+ ** not part of a varint */
+ while( p<pEnd && *p!=0x01 ){
+ while( *p++ & 0x80 );
+ }
+
+ if( pColset->aiCol[i]==iCurrent ){
+ if( pColset->nCol==1 ){
+ pIter->base.pData = aCopy;
+ pIter->base.nData = p-aCopy;
+ return;
+ }
+ fts5BufferSafeAppendBlob(&pIter->poslist, aCopy, p-aCopy);
+ }
+ if( p>=pEnd ){
+ pIter->base.pData = pIter->poslist.p;
+ pIter->base.nData = pIter->poslist.n;
+ return;
+ }
+ aCopy = p++;
+ iCurrent = *p++;
+ if( iCurrent & 0x80 ){
+ p--;
+ p += fts5GetVarint32(p, iCurrent);
}
}
}
+
}
/*
@@ -225661,16 +235931,9 @@ static void fts5IterSetOutputs_Full(Fts5Iter *pIter, Fts5SegIter *pSeg){
/* All data is stored on the current page. Populate the output
** variables to point into the body of the page object. */
const u8 *a = &pSeg->pLeaf->p[pSeg->iLeafOffset];
- if( pColset->nCol==1 ){
- pIter->base.nData = fts5IndexExtractCol(&a, pSeg->nPos,pColset->aiCol[0]);
- pIter->base.pData = a;
- }else{
- int *pRc = &pIter->pIndex->rc;
- fts5BufferZero(&pIter->poslist);
- fts5IndexExtractColset(pRc, pColset, a, pSeg->nPos, &pIter->poslist);
- pIter->base.pData = pIter->poslist.p;
- pIter->base.nData = pIter->poslist.n;
- }
+ int *pRc = &pIter->pIndex->rc;
+ fts5BufferZero(&pIter->poslist);
+ fts5IndexExtractColset(pRc, pColset, a, pSeg->nPos, pIter);
}else{
/* The data is distributed over two or more pages. Copy it into the
** Fts5Iter.poslist buffer and then set the output pointer to point
@@ -225683,6 +235946,7 @@ static void fts5IterSetOutputs_Full(Fts5Iter *pIter, Fts5SegIter *pSeg){
}
static void fts5IterSetOutputCb(int *pRc, Fts5Iter *pIter){
+ assert( pIter!=0 || (*pRc)!=SQLITE_OK );
if( *pRc==SQLITE_OK ){
Fts5Config *pConfig = pIter->pIndex->pConfig;
if( pConfig->eDetail==FTS5_DETAIL_NONE ){
@@ -225754,7 +236018,10 @@ static void fts5MultiIterNew(
}
}
*ppOut = pNew = fts5MultiIterAlloc(p, nSeg);
- if( pNew==0 ) return;
+ if( pNew==0 ){
+ assert( p->rc!=SQLITE_OK );
+ goto fts5MultiIterNew_post_check;
+ }
pNew->bRev = (0!=(flags & FTS5INDEX_QUERY_DESC));
pNew->bSkipEmpty = (0!=(flags & FTS5INDEX_QUERY_SKIPEMPTY));
pNew->pColset = pColset;
@@ -225818,6 +236085,10 @@ static void fts5MultiIterNew(
fts5MultiIterFree(pNew);
*ppOut = 0;
}
+
+fts5MultiIterNew_post_check:
+ assert( (*ppOut)!=0 || p->rc!=SQLITE_OK );
+ return;
}
/*
@@ -225865,7 +236136,8 @@ static void fts5MultiIterNew2(
** False otherwise.
*/
static int fts5MultiIterEof(Fts5Index *p, Fts5Iter *pIter){
- assert( p->rc
+ assert( pIter!=0 || p->rc!=SQLITE_OK );
+ assert( p->rc!=SQLITE_OK
|| (pIter->aSeg[ pIter->aFirst[1].iFirst ].pLeaf==0)==pIter->base.bEof
);
return (p->rc || pIter->base.bEof);
@@ -226669,6 +236941,7 @@ static void fts5IndexMergeLevel(
** and last leaf page number at the same time. */
fts5WriteFinish(p, &writer, &pSeg->pgnoLast);
+ assert( pIter!=0 || p->rc!=SQLITE_OK );
if( fts5MultiIterEof(p, pIter) ){
int i;
@@ -226769,7 +237042,7 @@ static void fts5IndexAutomerge(
Fts5Structure **ppStruct, /* IN/OUT: Current structure of index */
int nLeaf /* Number of output leaves just written */
){
- if( p->rc==SQLITE_OK && p->pConfig->nAutomerge>0 ){
+ if( p->rc==SQLITE_OK && p->pConfig->nAutomerge>0 && ALWAYS((*ppStruct)!=0) ){
Fts5Structure *pStruct = *ppStruct;
u64 nWrite; /* Initial value of write-counter */
int nWork; /* Number of work-quanta to perform */
@@ -226892,14 +237165,14 @@ static void fts5FlushOneHash(Fts5Index *p){
fts5BufferSafeAppendBlob(pBuf, pDoclist, nDoclist);
}else{
i64 iRowid = 0;
- i64 iDelta = 0;
+ u64 iDelta = 0;
int iOff = 0;
/* The entire doclist will not fit on this leaf. The following
** loop iterates through the poslists that make up the current
** doclist. */
while( p->rc==SQLITE_OK && iOff<nDoclist ){
- iOff += fts5GetVarint(&pDoclist[iOff], (u64*)&iDelta);
+ iOff += fts5GetVarint(&pDoclist[iOff], &iDelta);
iRowid += iDelta;
if( writer.bFirstRowidInPage ){
@@ -227153,7 +237426,7 @@ static void fts5AppendPoslist(
static void fts5DoclistIterNext(Fts5DoclistIter *pIter){
u8 *p = pIter->aPoslist + pIter->nSize + pIter->nPoslist;
- assert( pIter->aPoslist );
+ assert( pIter->aPoslist || (p==0 && pIter->aPoslist==0) );
if( p>=pIter->aEof ){
pIter->aPoslist = 0;
}else{
@@ -227173,6 +237446,9 @@ static void fts5DoclistIterNext(Fts5DoclistIter *pIter){
}
pIter->aPoslist = p;
+ if( &pIter->aPoslist[pIter->nPoslist]>pIter->aEof ){
+ pIter->aPoslist = 0;
+ }
}
}
@@ -227181,9 +237457,11 @@ static void fts5DoclistIterInit(
Fts5DoclistIter *pIter
){
memset(pIter, 0, sizeof(*pIter));
- pIter->aPoslist = pBuf->p;
- pIter->aEof = &pBuf->p[pBuf->n];
- fts5DoclistIterNext(pIter);
+ if( pBuf->n>0 ){
+ pIter->aPoslist = pBuf->p;
+ pIter->aEof = &pBuf->p[pBuf->n];
+ fts5DoclistIterNext(pIter);
+ }
}
#if 0
@@ -227237,16 +237515,20 @@ static void fts5NextRowid(Fts5Buffer *pBuf, int *piOff, i64 *piRowid){
static void fts5MergeRowidLists(
Fts5Index *p, /* FTS5 backend object */
Fts5Buffer *p1, /* First list to merge */
- Fts5Buffer *p2 /* Second list to merge */
+ int nBuf, /* Number of entries in apBuf[] */
+ Fts5Buffer *aBuf /* Array of other lists to merge into p1 */
){
int i1 = 0;
int i2 = 0;
i64 iRowid1 = 0;
i64 iRowid2 = 0;
i64 iOut = 0;
-
+ Fts5Buffer *p2 = &aBuf[0];
Fts5Buffer out;
+
+ (void)nBuf;
memset(&out, 0, sizeof(out));
+ assert( nBuf==1 );
sqlcipher_sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n);
if( p->rc ) return;
@@ -227273,180 +237555,214 @@ static void fts5MergeRowidLists(
fts5BufferFree(&out);
}
+typedef struct PrefixMerger PrefixMerger;
+struct PrefixMerger {
+ Fts5DoclistIter iter; /* Doclist iterator */
+ i64 iPos; /* For iterating through a position list */
+ int iOff;
+ u8 *aPos;
+ PrefixMerger *pNext; /* Next in docid/poslist order */
+};
+
+static void fts5PrefixMergerInsertByRowid(
+ PrefixMerger **ppHead,
+ PrefixMerger *p
+){
+ if( p->iter.aPoslist ){
+ PrefixMerger **pp = ppHead;
+ while( *pp && p->iter.iRowid>(*pp)->iter.iRowid ){
+ pp = &(*pp)->pNext;
+ }
+ p->pNext = *pp;
+ *pp = p;
+ }
+}
+
+static void fts5PrefixMergerInsertByPosition(
+ PrefixMerger **ppHead,
+ PrefixMerger *p
+){
+ if( p->iPos>=0 ){
+ PrefixMerger **pp = ppHead;
+ while( *pp && p->iPos>(*pp)->iPos ){
+ pp = &(*pp)->pNext;
+ }
+ p->pNext = *pp;
+ *pp = p;
+ }
+}
+
+
/*
-** Buffers p1 and p2 contain doclists. This function merges the content
-** of the two doclists together and sets buffer p1 to the result before
-** returning.
-**
-** If an error occurs, an error code is left in p->rc. If an error has
-** already occurred, this function is a no-op.
+** Array aBuf[] contains nBuf doclists. These are all merged in with the
+** doclist in buffer p1.
*/
static void fts5MergePrefixLists(
Fts5Index *p, /* FTS5 backend object */
Fts5Buffer *p1, /* First list to merge */
- Fts5Buffer *p2 /* Second list to merge */
-){
- if( p2->n ){
- i64 iLastRowid = 0;
- Fts5DoclistIter i1;
- Fts5DoclistIter i2;
- Fts5Buffer out = {0, 0, 0};
- Fts5Buffer tmp = {0, 0, 0};
-
- /* The maximum size of the output is equal to the sum of the two
- ** input sizes + 1 varint (9 bytes). The extra varint is because if the
- ** first rowid in one input is a large negative number, and the first in
- ** the other a non-negative number, the delta for the non-negative
- ** number will be larger on disk than the literal integer value
- ** was.
- **
- ** Or, if the input position-lists are corrupt, then the output might
- ** include up to 2 extra 10-byte positions created by interpreting -1
- ** (the value PoslistNext64() uses for EOF) as a position and appending
- ** it to the output. This can happen at most once for each input
- ** position-list, hence two 10 byte paddings. */
- if( sqlcipher_sqlite3Fts5BufferSize(&p->rc, &out, p1->n + p2->n + 9+10+10) ) return;
- fts5DoclistIterInit(p1, &i1);
- fts5DoclistIterInit(p2, &i2);
+ int nBuf, /* Number of buffers in array aBuf[] */
+ Fts5Buffer *aBuf /* Other lists to merge in */
+){
+#define fts5PrefixMergerNextPosition(p) \
+ sqlcipher_sqlite3Fts5PoslistNext64((p)->aPos,(p)->iter.nPoslist,&(p)->iOff,&(p)->iPos)
+#define FTS5_MERGE_NLIST 16
+ PrefixMerger aMerger[FTS5_MERGE_NLIST];
+ PrefixMerger *pHead = 0;
+ int i;
+ int nOut = 0;
+ Fts5Buffer out = {0, 0, 0};
+ Fts5Buffer tmp = {0, 0, 0};
+ i64 iLastRowid = 0;
+
+ /* Initialize a doclist-iterator for each input buffer. Arrange them in
+ ** a linked-list starting at pHead in ascending order of rowid. Avoid
+ ** linking any iterators already at EOF into the linked list at all. */
+ assert( nBuf+1<=sizeof(aMerger)/sizeof(aMerger[0]) );
+ memset(aMerger, 0, sizeof(PrefixMerger)*(nBuf+1));
+ pHead = &aMerger[nBuf];
+ fts5DoclistIterInit(p1, &pHead->iter);
+ for(i=0; i<nBuf; i++){
+ fts5DoclistIterInit(&aBuf[i], &aMerger[i].iter);
+ fts5PrefixMergerInsertByRowid(&pHead, &aMerger[i]);
+ nOut += aBuf[i].n;
+ }
+ if( nOut==0 ) return;
+ nOut += p1->n + 9 + 10*nBuf;
+
+ /* The maximum size of the output is equal to the sum of the
+ ** input sizes + 1 varint (9 bytes). The extra varint is because if the
+ ** first rowid in one input is a large negative number, and the first in
+ ** the other a non-negative number, the delta for the non-negative
+ ** number will be larger on disk than the literal integer value
+ ** was.
+ **
+ ** Or, if the input position-lists are corrupt, then the output might
+ ** include up to (nBuf+1) extra 10-byte positions created by interpreting -1
+ ** (the value PoslistNext64() uses for EOF) as a position and appending
+ ** it to the output. This can happen at most once for each input
+ ** position-list, hence (nBuf+1) 10 byte paddings. */
+ if( sqlcipher_sqlite3Fts5BufferSize(&p->rc, &out, nOut) ) return;
+
+ while( pHead ){
+ fts5MergeAppendDocid(&out, iLastRowid, pHead->iter.iRowid);
+
+ if( pHead->pNext && iLastRowid==pHead->pNext->iter.iRowid ){
+ /* Merge data from two or more poslists */
+ i64 iPrev = 0;
+ int nTmp = FTS5_DATA_ZERO_PADDING;
+ int nMerge = 0;
+ PrefixMerger *pSave = pHead;
+ PrefixMerger *pThis = 0;
+ int nTail = 0;
+
+ pHead = 0;
+ while( pSave && pSave->iter.iRowid==iLastRowid ){
+ PrefixMerger *pNext = pSave->pNext;
+ pSave->iOff = 0;
+ pSave->iPos = 0;
+ pSave->aPos = &pSave->iter.aPoslist[pSave->iter.nSize];
+ fts5PrefixMergerNextPosition(pSave);
+ nTmp += pSave->iter.nPoslist + 10;
+ nMerge++;
+ fts5PrefixMergerInsertByPosition(&pHead, pSave);
+ pSave = pNext;
+ }
+
+ if( pHead==0 || pHead->pNext==0 ){
+ p->rc = FTS5_CORRUPT;
+ break;
+ }
- while( 1 ){
- if( i1.iRowid<i2.iRowid ){
- /* Copy entry from i1 */
- fts5MergeAppendDocid(&out, iLastRowid, i1.iRowid);
- fts5BufferSafeAppendBlob(&out, i1.aPoslist, i1.nPoslist+i1.nSize);
- fts5DoclistIterNext(&i1);
- if( i1.aPoslist==0 ) break;
- assert( out.n<=((i1.aPoslist-p1->p) + (i2.aPoslist-p2->p)+9+10+10) );
- }
- else if( i2.iRowid!=i1.iRowid ){
- /* Copy entry from i2 */
- fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid);
- fts5BufferSafeAppendBlob(&out, i2.aPoslist, i2.nPoslist+i2.nSize);
- fts5DoclistIterNext(&i2);
- if( i2.aPoslist==0 ) break;
- assert( out.n<=((i1.aPoslist-p1->p) + (i2.aPoslist-p2->p)+9+10+10) );
+ /* See the earlier comment in this function for an explanation of why
+ ** corrupt input position lists might cause the output to consume
+ ** at most nMerge*10 bytes of unexpected space. */
+ if( sqlcipher_sqlite3Fts5BufferSize(&p->rc, &tmp, nTmp+nMerge*10) ){
+ break;
}
- else{
- /* Merge the two position lists. */
- i64 iPos1 = 0;
- i64 iPos2 = 0;
- int iOff1 = 0;
- int iOff2 = 0;
- u8 *a1 = &i1.aPoslist[i1.nSize];
- u8 *a2 = &i2.aPoslist[i2.nSize];
- int nCopy;
- u8 *aCopy;
-
- i64 iPrev = 0;
- Fts5PoslistWriter writer;
- memset(&writer, 0, sizeof(writer));
-
- /* See the earlier comment in this function for an explanation of why
- ** corrupt input position lists might cause the output to consume
- ** at most 20 bytes of unexpected space. */
- fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid);
- fts5BufferZero(&tmp);
- sqlcipher_sqlite3Fts5BufferSize(&p->rc, &tmp,
- i1.nPoslist + i2.nPoslist + 10 + 10 + FTS5_DATA_ZERO_PADDING
- );
- if( p->rc ) break;
+ fts5BufferZero(&tmp);
- sqlcipher_sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1);
- sqlcipher_sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2);
- assert_nc( iPos1>=0 && iPos2>=0 );
+ pThis = pHead;
+ pHead = pThis->pNext;
+ sqlcipher_sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, pThis->iPos);
+ fts5PrefixMergerNextPosition(pThis);
+ fts5PrefixMergerInsertByPosition(&pHead, pThis);
- if( iPos1<iPos2 ){
- sqlcipher_sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos1);
- sqlcipher_sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1);
- }else{
- sqlcipher_sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos2);
- sqlcipher_sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2);
- }
- if( iPos1>=0 && iPos2>=0 ){
- while( 1 ){
- if( iPos1<iPos2 ){
- if( iPos1!=iPrev ){
- sqlcipher_sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos1);
- }
- sqlcipher_sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1);
- if( iPos1<0 ) break;
- }else{
- assert_nc( iPos2!=iPrev );
- sqlcipher_sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos2);
- sqlcipher_sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2);
- if( iPos2<0 ) break;
- }
- }
+ while( pHead->pNext ){
+ pThis = pHead;
+ if( pThis->iPos!=iPrev ){
+ sqlcipher_sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, pThis->iPos);
}
+ fts5PrefixMergerNextPosition(pThis);
+ pHead = pThis->pNext;
+ fts5PrefixMergerInsertByPosition(&pHead, pThis);
+ }
- if( iPos1>=0 ){
- if( iPos1!=iPrev ){
- sqlcipher_sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos1);
- }
- aCopy = &a1[iOff1];
- nCopy = i1.nPoslist - iOff1;
- }else{
- assert_nc( iPos2>=0 && iPos2!=iPrev );
- sqlcipher_sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, iPos2);
- aCopy = &a2[iOff2];
- nCopy = i2.nPoslist - iOff2;
- }
- if( nCopy>0 ){
- fts5BufferSafeAppendBlob(&tmp, aCopy, nCopy);
- }
+ if( pHead->iPos!=iPrev ){
+ sqlcipher_sqlite3Fts5PoslistSafeAppend(&tmp, &iPrev, pHead->iPos);
+ }
+ nTail = pHead->iter.nPoslist - pHead->iOff;
- /* WRITEPOSLISTSIZE */
- assert_nc( tmp.n<=i1.nPoslist+i2.nPoslist );
- assert( tmp.n<=i1.nPoslist+i2.nPoslist+10+10 );
- if( tmp.n>i1.nPoslist+i2.nPoslist ){
- if( p->rc==SQLITE_OK ) p->rc = FTS5_CORRUPT;
- break;
+ /* WRITEPOSLISTSIZE */
+ assert_nc( tmp.n+nTail<=nTmp );
+ assert( tmp.n+nTail<=nTmp+nMerge*10 );
+ if( tmp.n+nTail>nTmp-FTS5_DATA_ZERO_PADDING ){
+ if( p->rc==SQLITE_OK ) p->rc = FTS5_CORRUPT;
+ break;
+ }
+ fts5BufferSafeAppendVarint(&out, (tmp.n+nTail) * 2);
+ fts5BufferSafeAppendBlob(&out, tmp.p, tmp.n);
+ if( nTail>0 ){
+ fts5BufferSafeAppendBlob(&out, &pHead->aPos[pHead->iOff], nTail);
+ }
+
+ pHead = pSave;
+ for(i=0; i<nBuf+1; i++){
+ PrefixMerger *pX = &aMerger[i];
+ if( pX->iter.aPoslist && pX->iter.iRowid==iLastRowid ){
+ fts5DoclistIterNext(&pX->iter);
+ fts5PrefixMergerInsertByRowid(&pHead, pX);
}
- fts5BufferSafeAppendVarint(&out, tmp.n * 2);
- fts5BufferSafeAppendBlob(&out, tmp.p, tmp.n);
- fts5DoclistIterNext(&i1);
- fts5DoclistIterNext(&i2);
- assert_nc( out.n<=(p1->n+p2->n+9) );
- if( i1.aPoslist==0 || i2.aPoslist==0 ) break;
- assert( out.n<=((i1.aPoslist-p1->p) + (i2.aPoslist-p2->p)+9+10+10) );
}
- }
- if( i1.aPoslist ){
- fts5MergeAppendDocid(&out, iLastRowid, i1.iRowid);
- fts5BufferSafeAppendBlob(&out, i1.aPoslist, i1.aEof - i1.aPoslist);
- }
- else if( i2.aPoslist ){
- fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid);
- fts5BufferSafeAppendBlob(&out, i2.aPoslist, i2.aEof - i2.aPoslist);
+ }else{
+ /* Copy poslist from pHead to output */
+ PrefixMerger *pThis = pHead;
+ Fts5DoclistIter *pI = &pThis->iter;
+ fts5BufferSafeAppendBlob(&out, pI->aPoslist, pI->nPoslist+pI->nSize);
+ fts5DoclistIterNext(pI);
+ pHead = pThis->pNext;
+ fts5PrefixMergerInsertByRowid(&pHead, pThis);
}
- assert_nc( out.n<=(p1->n+p2->n+9) );
-
- fts5BufferFree(p1);
- fts5BufferFree(&tmp);
- memset(&out.p[out.n], 0, FTS5_DATA_ZERO_PADDING);
- *p1 = out;
}
+
+ fts5BufferFree(p1);
+ fts5BufferFree(&tmp);
+ memset(&out.p[out.n], 0, FTS5_DATA_ZERO_PADDING);
+ *p1 = out;
}
static void fts5SetupPrefixIter(
Fts5Index *p, /* Index to read from */
int bDesc, /* True for "ORDER BY rowid DESC" */
- const u8 *pToken, /* Buffer containing prefix to match */
+ int iIdx, /* Index to scan for data */
+ u8 *pToken, /* Buffer containing prefix to match */
int nToken, /* Size of buffer pToken in bytes */
Fts5Colset *pColset, /* Restrict matches to these columns */
Fts5Iter **ppIter /* OUT: New iterator */
){
Fts5Structure *pStruct;
Fts5Buffer *aBuf;
- const int nBuf = 32;
+ int nBuf = 32;
+ int nMerge = 1;
- void (*xMerge)(Fts5Index*, Fts5Buffer*, Fts5Buffer*);
+ void (*xMerge)(Fts5Index*, Fts5Buffer*, int, Fts5Buffer*);
void (*xAppend)(Fts5Index*, i64, Fts5Iter*, Fts5Buffer*);
if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){
xMerge = fts5MergeRowidLists;
xAppend = fts5AppendRowid;
}else{
+ nMerge = FTS5_MERGE_NLIST-1;
+ nBuf = nMerge*8; /* Sufficient to merge (16^8)==(2^32) lists */
xMerge = fts5MergePrefixLists;
xAppend = fts5AppendPoslist;
}
@@ -227466,6 +237782,27 @@ static void fts5SetupPrefixIter(
int bNewTerm = 1;
memset(&doclist, 0, sizeof(doclist));
+ if( iIdx!=0 ){
+ int dummy = 0;
+ const int f2 = FTS5INDEX_QUERY_SKIPEMPTY|FTS5INDEX_QUERY_NOOUTPUT;
+ pToken[0] = FTS5_MAIN_PREFIX;
+ fts5MultiIterNew(p, pStruct, f2, pColset, pToken, nToken, -1, 0, &p1);
+ fts5IterSetOutputCb(&p->rc, p1);
+ for(;
+ fts5MultiIterEof(p, p1)==0;
+ fts5MultiIterNext2(p, p1, &dummy)
+ ){
+ Fts5SegIter *pSeg = &p1->aSeg[ p1->aFirst[1].iFirst ];
+ p1->xSetOutputs(p1, pSeg);
+ if( p1->base.nData ){
+ xAppend(p, p1->base.iRowid-iLastRowid, p1, &doclist);
+ iLastRowid = p1->base.iRowid;
+ }
+ }
+ fts5MultiIterFree(p1);
+ }
+
+ pToken[0] = FTS5_MAIN_PREFIX + iIdx;
fts5MultiIterNew(p, pStruct, flags, pColset, pToken, nToken, -1, 0, &p1);
fts5IterSetOutputCb(&p->rc, p1);
for( /* no-op */ ;
@@ -227486,13 +237823,21 @@ static void fts5SetupPrefixIter(
if( p1->base.iRowid<=iLastRowid && doclist.n>0 ){
for(i=0; p->rc==SQLITE_OK && doclist.n; i++){
- assert( i<nBuf );
- if( aBuf[i].n==0 ){
- fts5BufferSwap(&doclist, &aBuf[i]);
- fts5BufferZero(&doclist);
- }else{
- xMerge(p, &doclist, &aBuf[i]);
- fts5BufferZero(&aBuf[i]);
+ int i1 = i*nMerge;
+ int iStore;
+ assert( i1+nMerge<=nBuf );
+ for(iStore=i1; iStore<i1+nMerge; iStore++){
+ if( aBuf[iStore].n==0 ){
+ fts5BufferSwap(&doclist, &aBuf[iStore]);
+ fts5BufferZero(&doclist);
+ break;
+ }
+ }
+ if( iStore==i1+nMerge ){
+ xMerge(p, &doclist, nMerge, &aBuf[i1]);
+ for(iStore=i1; iStore<i1+nMerge; iStore++){
+ fts5BufferZero(&aBuf[iStore]);
+ }
}
}
iLastRowid = 0;
@@ -227502,11 +237847,15 @@ static void fts5SetupPrefixIter(
iLastRowid = p1->base.iRowid;
}
- for(i=0; i<nBuf; i++){
+ assert( (nBuf%nMerge)==0 );
+ for(i=0; i<nBuf; i+=nMerge){
+ int iFree;
if( p->rc==SQLITE_OK ){
- xMerge(p, &doclist, &aBuf[i]);
+ xMerge(p, &doclist, nMerge, &aBuf[i]);
+ }
+ for(iFree=i; iFree<i+nMerge; iFree++){
+ fts5BufferFree(&aBuf[iFree]);
}
- fts5BufferFree(&aBuf[i]);
}
fts5MultiIterFree(p1);
@@ -227761,7 +238110,8 @@ static int sqlcipher_sqlite3Fts5IndexQuery(
if( sqlcipher_sqlite3Fts5BufferSize(&p->rc, &buf, nToken+1)==0 ){
int iIdx = 0; /* Index to search */
- if( nToken ) memcpy(&buf.p[1], pToken, nToken);
+ int iPrefixIdx = 0; /* +1 prefix index */
+ if( nToken>0 ) memcpy(&buf.p[1], pToken, nToken);
/* Figure out which index to search and set iIdx accordingly. If this
** is a prefix query for which there is no prefix index, set iIdx to
@@ -227782,7 +238132,9 @@ static int sqlcipher_sqlite3Fts5IndexQuery(
if( flags & FTS5INDEX_QUERY_PREFIX ){
int nChar = fts5IndexCharlen(pToken, nToken);
for(iIdx=1; iIdx<=pConfig->nPrefix; iIdx++){
- if( pConfig->aPrefix[iIdx-1]==nChar ) break;
+ int nIdxChar = pConfig->aPrefix[iIdx-1];
+ if( nIdxChar==nChar ) break;
+ if( nIdxChar==nChar+1 ) iPrefixIdx = iIdx;
}
}
@@ -227799,13 +238151,16 @@ static int sqlcipher_sqlite3Fts5IndexQuery(
}else{
/* Scan multiple terms in the main index */
int bDesc = (flags & FTS5INDEX_QUERY_DESC)!=0;
- buf.p[0] = FTS5_MAIN_PREFIX;
- fts5SetupPrefixIter(p, bDesc, buf.p, nToken+1, pColset, &pRet);
- assert( p->rc!=SQLITE_OK || pRet->pColset==0 );
- fts5IterSetOutputCb(&p->rc, pRet);
- if( p->rc==SQLITE_OK ){
- Fts5SegIter *pSeg = &pRet->aSeg[pRet->aFirst[1].iFirst];
- if( pSeg->pLeaf ) pRet->xSetOutputs(pRet, pSeg);
+ fts5SetupPrefixIter(p, bDesc, iPrefixIdx, buf.p, nToken+1, pColset,&pRet);
+ if( pRet==0 ){
+ assert( p->rc!=SQLITE_OK );
+ }else{
+ assert( pRet->pColset==0 );
+ fts5IterSetOutputCb(&p->rc, pRet);
+ if( p->rc==SQLITE_OK ){
+ Fts5SegIter *pSeg = &pRet->aSeg[pRet->aFirst[1].iFirst];
+ if( pSeg->pLeaf ) pRet->xSetOutputs(pRet, pSeg);
+ }
}
}
@@ -227873,8 +238228,9 @@ static int sqlcipher_sqlite3Fts5IterNextFrom(Fts5IndexIter *pIndexIter, i64 iMat
static const char *sqlcipher_sqlite3Fts5IterTerm(Fts5IndexIter *pIndexIter, int *pn){
int n;
const char *z = (const char*)fts5MultiIterTerm((Fts5Iter*)pIndexIter, &n);
+ assert_nc( z || n<=1 );
*pn = n-1;
- return &z[1];
+ return (z ? &z[1] : 0);
}
/*
@@ -228052,7 +238408,7 @@ static int fts5QueryCksum(
Fts5IndexIter *pIter = 0;
int rc = sqlcipher_sqlite3Fts5IndexQuery(p, z, n, flags, 0, &pIter);
- while( rc==SQLITE_OK && 0==sqlcipher_sqlite3Fts5IterEof(pIter) ){
+ while( rc==SQLITE_OK && ALWAYS(pIter!=0) && 0==sqlcipher_sqlite3Fts5IterEof(pIter) ){
i64 rowid = pIter->iRowid;
if( eDetail==FTS5_DETAIL_NONE ){
@@ -228417,6 +238773,7 @@ static int sqlcipher_sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum, int
Fts5Buffer poslist = {0,0,0}; /* Buffer used to hold a poslist */
Fts5Iter *pIter; /* Used to iterate through entire index */
Fts5Structure *pStruct; /* Index structure */
+ int iLvl, iSeg;
#ifdef SQLITE_DEBUG
/* Used by extra internal tests only run if NDEBUG is not defined */
@@ -228427,15 +238784,16 @@ static int sqlcipher_sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum, int
/* Load the FTS index structure */
pStruct = fts5StructureRead(p);
+ if( pStruct==0 ){
+ assert( p->rc!=SQLITE_OK );
+ return fts5IndexReturn(p);
+ }
/* Check that the internal nodes of each segment match the leaves */
- if( pStruct ){
- int iLvl, iSeg;
- for(iLvl=0; iLvl<pStruct->nLevel; iLvl++){
- for(iSeg=0; iSeg<pStruct->aLevel[iLvl].nSeg; iSeg++){
- Fts5StructureSegment *pSeg = &pStruct->aLevel[iLvl].aSeg[iSeg];
- fts5IndexIntegrityCheckSegment(p, pSeg);
- }
+ for(iLvl=0; iLvl<pStruct->nLevel; iLvl++){
+ for(iSeg=0; iSeg<pStruct->aLevel[iLvl].nSeg; iSeg++){
+ Fts5StructureSegment *pSeg = &pStruct->aLevel[iLvl].aSeg[iSeg];
+ fts5IndexIntegrityCheckSegment(p, pSeg);
}
}
@@ -228499,6 +238857,7 @@ static int sqlcipher_sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum, int
** function only.
*/
+#ifdef SQLITE_TEST
/*
** Decode a segment-data rowid from the %_data table. This function is
** the opposite of macro FTS5_SEGMENT_ROWID().
@@ -228521,7 +238880,9 @@ static void fts5DecodeRowid(
*piSegid = (int)(iRowid & (((i64)1 << FTS5_DATA_ID_B) - 1));
}
+#endif /* SQLITE_TEST */
+#ifdef SQLITE_TEST
static void fts5DebugRowid(int *pRc, Fts5Buffer *pBuf, i64 iKey){
int iSegid, iHeight, iPgno, bDlidx; /* Rowid compenents */
fts5DecodeRowid(iKey, &iSegid, &bDlidx, &iHeight, &iPgno);
@@ -228539,7 +238900,9 @@ static void fts5DebugRowid(int *pRc, Fts5Buffer *pBuf, i64 iKey){
);
}
}
+#endif /* SQLITE_TEST */
+#ifdef SQLITE_TEST
static void fts5DebugStructure(
int *pRc, /* IN/OUT: error code */
Fts5Buffer *pBuf,
@@ -228561,7 +238924,9 @@ static void fts5DebugStructure(
sqlcipher_sqlite3Fts5BufferAppendPrintf(pRc, pBuf, "}");
}
}
+#endif /* SQLITE_TEST */
+#ifdef SQLITE_TEST
/*
** This is part of the fts5_decode() debugging aid.
**
@@ -228586,7 +238951,9 @@ static void fts5DecodeStructure(
fts5DebugStructure(pRc, pBuf, p);
fts5StructureRelease(p);
}
+#endif /* SQLITE_TEST */
+#ifdef SQLITE_TEST
/*
** This is part of the fts5_decode() debugging aid.
**
@@ -228609,7 +238976,9 @@ static void fts5DecodeAverages(
zSpace = " ";
}
}
+#endif /* SQLITE_TEST */
+#ifdef SQLITE_TEST
/*
** Buffer (a/n) is assumed to contain a list of serialized varints. Read
** each varint and append its string representation to buffer pBuf. Return
@@ -228626,7 +238995,9 @@ static int fts5DecodePoslist(int *pRc, Fts5Buffer *pBuf, const u8 *a, int n){
}
return iOff;
}
+#endif /* SQLITE_TEST */
+#ifdef SQLITE_TEST
/*
** The start of buffer (a/n) contains the start of a doclist. The doclist
** may or may not finish within the buffer. This function appends a text
@@ -228659,7 +239030,9 @@ static int fts5DecodeDoclist(int *pRc, Fts5Buffer *pBuf, const u8 *a, int n){
return iOff;
}
+#endif /* SQLITE_TEST */
+#ifdef SQLITE_TEST
/*
** This function is part of the fts5_decode() debugging function. It is
** only ever used with detail=none tables.
@@ -228700,7 +239073,9 @@ static void fts5DecodeRowidList(
sqlcipher_sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " %lld%s", iRowid, zApp);
}
}
+#endif /* SQLITE_TEST */
+#ifdef SQLITE_TEST
/*
** The implementation of user-defined scalar function fts5_decode().
*/
@@ -228909,7 +239284,9 @@ static void fts5DecodeFunction(
}
fts5BufferFree(&s);
}
+#endif /* SQLITE_TEST */
+#ifdef SQLITE_TEST
/*
** The implementation of user-defined scalar function fts5_rowid().
*/
@@ -228943,6 +239320,7 @@ static void fts5RowidFunction(
}
}
}
+#endif /* SQLITE_TEST */
/*
** This is called as part of registering the FTS5 module with database
@@ -228953,6 +239331,7 @@ static void fts5RowidFunction(
** SQLite error code is returned instead.
*/
static int sqlcipher_sqlite3Fts5IndexInit(sqlcipher_sqlite3 *db){
+#ifdef SQLITE_TEST
int rc = sqlcipher_sqlite3_create_function(
db, "fts5_decode", 2, SQLITE_UTF8, 0, fts5DecodeFunction, 0, 0
);
@@ -228970,6 +239349,10 @@ static int sqlcipher_sqlite3Fts5IndexInit(sqlcipher_sqlite3 *db){
);
}
return rc;
+#else
+ return SQLITE_OK;
+ UNUSED_PARAM(db);
+#endif
}
@@ -229005,7 +239388,9 @@ static int sqlcipher_sqlite3Fts5IndexReset(Fts5Index *p){
** assert() conditions in the fts5 code are activated - conditions that are
** only true if it is guaranteed that the fts5 database is not corrupt.
*/
+#ifdef SQLITE_DEBUG
SQLITE_API int sqlcipher_sqlite3_fts5_may_be_corrupt = 1;
+#endif
typedef struct Fts5Auxdata Fts5Auxdata;
@@ -229785,7 +240170,7 @@ static int fts5SorterNext(Fts5Cursor *pCsr){
rc = sqlcipher_sqlite3_step(pSorter->pStmt);
if( rc==SQLITE_DONE ){
rc = SQLITE_OK;
- CsrFlagSet(pCsr, FTS5CSR_EOF);
+ CsrFlagSet(pCsr, FTS5CSR_EOF|FTS5CSR_REQUIRE_CONTENT);
}else if( rc==SQLITE_ROW ){
const u8 *a;
const u8 *aBlob;
@@ -230355,7 +240740,8 @@ static int fts5FilterMethod(
pTab->pStorage, fts5StmtType(pCsr), &pCsr->pStmt, &pTab->p.base.zErrMsg
);
if( rc==SQLITE_OK ){
- if( pCsr->ePlan==FTS5_PLAN_ROWID ){
+ if( pRowidEq!=0 ){
+ assert( pCsr->ePlan==FTS5_PLAN_ROWID );
sqlcipher_sqlite3_bind_value(pCsr->pStmt, 1, pRowidEq);
}else{
sqlcipher_sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iFirstRowid);
@@ -230930,13 +241316,15 @@ static int fts5CacheInstArray(Fts5Cursor *pCsr){
nInst++;
if( nInst>=pCsr->nInstAlloc ){
- pCsr->nInstAlloc = pCsr->nInstAlloc ? pCsr->nInstAlloc*2 : 32;
+ int nNewSize = pCsr->nInstAlloc ? pCsr->nInstAlloc*2 : 32;
aInst = (int*)sqlcipher_sqlite3_realloc64(
- pCsr->aInst, pCsr->nInstAlloc*sizeof(int)*3
+ pCsr->aInst, nNewSize*sizeof(int)*3
);
if( aInst ){
pCsr->aInst = aInst;
+ pCsr->nInstAlloc = nNewSize;
}else{
+ nInst--;
rc = SQLITE_NOMEM;
break;
}
@@ -231160,7 +241548,8 @@ static int fts5ApiPhraseFirst(
int n;
int rc = fts5CsrPoslist(pCsr, iPhrase, &pIter->a, &n);
if( rc==SQLITE_OK ){
- pIter->b = &pIter->a[n];
+ assert( pIter->a || n==0 );
+ pIter->b = (pIter->a ? &pIter->a[n] : 0);
*piCol = 0;
*piOff = 0;
fts5ApiPhraseNext(pCtx, pIter, piCol, piOff);
@@ -231219,7 +241608,8 @@ static int fts5ApiPhraseFirstColumn(
rc = sqlcipher_sqlite3Fts5ExprPhraseCollist(pCsr->pExpr, iPhrase, &pIter->a, &n);
}
if( rc==SQLITE_OK ){
- pIter->b = &pIter->a[n];
+ assert( pIter->a || n==0 );
+ pIter->b = (pIter->a ? &pIter->a[n] : 0);
*piCol = 0;
fts5ApiPhraseNextColumn(pCtx, pIter, piCol);
}
@@ -231227,7 +241617,8 @@ static int fts5ApiPhraseFirstColumn(
int n;
rc = fts5CsrPoslist(pCsr, iPhrase, &pIter->a, &n);
if( rc==SQLITE_OK ){
- pIter->b = &pIter->a[n];
+ assert( pIter->a || n==0 );
+ pIter->b = (pIter->a ? &pIter->a[n] : 0);
if( n<=0 ){
*piCol = -1;
}else if( pIter->a[0]==0x01 ){
@@ -231705,7 +242096,7 @@ static int sqlcipher_sqlite3Fts5GetTokenizer(
*pzErr = sqlcipher_sqlite3_mprintf("no such tokenizer: %s", azArg[0]);
}else{
rc = pMod->x.xCreate(
- pMod->pUserData, &azArg[1], (nArg?nArg-1:0), &pConfig->pTok
+ pMod->pUserData, (azArg?&azArg[1]:0), (nArg?nArg-1:0), &pConfig->pTok
);
pConfig->pTokApi = &pMod->x;
if( rc!=SQLITE_OK ){
@@ -231768,7 +242159,7 @@ static void fts5SourceIdFunc(
){
assert( nArg==0 );
UNUSED_PARAM2(nArg, apUnused);
- sqlcipher_sqlite3_result_text(pCtx, "fts5: 2021-01-20 14:10:07 10e20c0b43500cfb9bbc0eaa061c57514f715d87238f4d835880cd846b9ebd1f", -1, SQLITE_TRANSIENT);
+ sqlcipher_sqlite3_result_text(pCtx, "fts5: 2022-09-29 15:55:41 a29f9949895322123f7c38fbe94c649a9d6e6c9cd0c3b41c96d694552f26b309", -1, SQLITE_TRANSIENT);
}
/*
@@ -232319,12 +242710,16 @@ static int fts5StorageDeleteFromIndex(
if( pConfig->abUnindexed[iCol-1]==0 ){
const char *zText;
int nText;
+ assert( pSeek==0 || apVal==0 );
+ assert( pSeek!=0 || apVal!=0 );
if( pSeek ){
zText = (const char*)sqlcipher_sqlite3_column_text(pSeek, iCol);
nText = sqlcipher_sqlite3_column_bytes(pSeek, iCol);
- }else{
+ }else if( ALWAYS(apVal) ){
zText = (const char*)sqlcipher_sqlite3_value_text(apVal[iCol-1]);
nText = sqlcipher_sqlite3_value_bytes(apVal[iCol-1]);
+ }else{
+ continue;
}
ctx.szCol = 0;
rc = sqlcipher_sqlite3Fts5Tokenize(pConfig, FTS5_TOKENIZE_DOCUMENT,
@@ -232960,8 +243355,9 @@ static int sqlcipher_sqlite3Fts5StorageDocsize(Fts5Storage *p, i64 iRowid, int *
assert( p->pConfig->bColumnsize );
rc = fts5StorageGetStmt(p, FTS5_STMT_LOOKUP_DOCSIZE, &pLookup, 0);
- if( rc==SQLITE_OK ){
+ if( pLookup ){
int bCorrupt = 1;
+ assert( rc==SQLITE_OK );
sqlcipher_sqlite3_bind_int64(pLookup, 1, iRowid);
if( SQLITE_ROW==sqlcipher_sqlite3_step(pLookup) ){
const u8 *aBlob = sqlcipher_sqlite3_column_blob(pLookup, 0);
@@ -232974,6 +243370,8 @@ static int sqlcipher_sqlite3Fts5StorageDocsize(Fts5Storage *p, i64 iRowid, int *
if( bCorrupt && rc==SQLITE_OK ){
rc = FTS5_CORRUPT;
}
+ }else{
+ assert( rc!=SQLITE_OK );
}
return rc;
@@ -235664,6 +246062,7 @@ struct Fts5VocabCursor {
int bEof; /* True if this cursor is at EOF */
Fts5IndexIter *pIter; /* Term/rowid iterator object */
+ void *pStruct; /* From sqlcipher_sqlite3Fts5StructureRef() */
int nLeTerm; /* Size of zLeTerm in bytes */
char *zLeTerm; /* (term <= $zLeTerm) paramater, or NULL */
@@ -235977,7 +246376,7 @@ static int fts5VocabOpenMethod(
}
if( rc==SQLITE_OK ){
- int nByte = pFts5->pConfig->nCol * sizeof(i64)*2 + sizeof(Fts5VocabCursor);
+ i64 nByte = pFts5->pConfig->nCol * sizeof(i64)*2 + sizeof(Fts5VocabCursor);
pCsr = (Fts5VocabCursor*)sqlcipher_sqlite3Fts5MallocZero(&rc, nByte);
}
@@ -235997,6 +246396,8 @@ static int fts5VocabOpenMethod(
static void fts5VocabResetCursor(Fts5VocabCursor *pCsr){
pCsr->rowid = 0;
sqlcipher_sqlite3Fts5IterClose(pCsr->pIter);
+ sqlcipher_sqlite3Fts5StructureRelease(pCsr->pStruct);
+ pCsr->pStruct = 0;
pCsr->pIter = 0;
sqlcipher_sqlite3_free(pCsr->zLeTerm);
pCsr->nLeTerm = -1;
@@ -236074,9 +246475,11 @@ static int fts5VocabInstanceNext(Fts5VocabCursor *pCsr){
static int fts5VocabNextMethod(sqlcipher_sqlite3_vtab_cursor *pCursor){
Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
Fts5VocabTable *pTab = (Fts5VocabTable*)pCursor->pVtab;
- int rc = SQLITE_OK;
int nCol = pCsr->pFts5->pConfig->nCol;
+ int rc;
+ rc = sqlcipher_sqlite3Fts5StructureTest(pCsr->pFts5->pIndex, pCsr->pStruct);
+ if( rc!=SQLITE_OK ) return rc;
pCsr->rowid++;
if( pTab->eType==FTS5_VOCAB_INSTANCE ){
@@ -236250,6 +246653,9 @@ static int fts5VocabFilterMethod(
if( rc==SQLITE_OK ){
Fts5Index *pIndex = pCsr->pFts5->pIndex;
rc = sqlcipher_sqlite3Fts5IndexQuery(pIndex, zTerm, nTerm, f, 0, &pCsr->pIter);
+ if( rc==SQLITE_OK ){
+ pCsr->pStruct = sqlcipher_sqlite3Fts5StructureRef(pIndex);
+ }
}
if( rc==SQLITE_OK && eType==FTS5_VOCAB_INSTANCE ){
rc = fts5VocabInstanceNewTerm(pCsr);
@@ -236424,6 +246830,16 @@ SQLITE_EXTENSION_INIT1
#ifndef SQLITE_OMIT_VIRTUALTABLE
+
+#define STMT_NUM_INTEGER_COLUMN 10
+typedef struct StmtRow StmtRow;
+struct StmtRow {
+ sqlcipher_sqlite3_int64 iRowid; /* Rowid value */
+ char *zSql; /* column "sql" */
+ int aCol[STMT_NUM_INTEGER_COLUMN+1]; /* all other column values */
+ StmtRow *pNext; /* Next row to return */
+};
+
/* stmt_vtab is a subclass of sqlcipher_sqlite3_vtab which will
** serve as the underlying representation of a stmt virtual table
*/
@@ -236441,8 +246857,7 @@ typedef struct stmt_cursor stmt_cursor;
struct stmt_cursor {
sqlcipher_sqlite3_vtab_cursor base; /* Base class - must be first */
sqlcipher_sqlite3 *db; /* Database connection for this cursor */
- sqlcipher_sqlite3_stmt *pStmt; /* Statement cursor is currently pointing at */
- sqlcipher_sqlite3_int64 iRowid; /* The rowid */
+ StmtRow *pRow; /* Current row */
};
/*
@@ -236486,7 +246901,7 @@ static int stmtConnect(
"CREATE TABLE x(sql,ncol,ro,busy,nscan,nsort,naidx,nstep,"
"reprep,run,mem)");
if( rc==SQLITE_OK ){
- pNew = sqlcipher_sqlite3_malloc( sizeof(*pNew) );
+ pNew = sqlcipher_sqlite3_malloc64( sizeof(*pNew) );
*ppVtab = (sqlcipher_sqlite3_vtab*)pNew;
if( pNew==0 ) return SQLITE_NOMEM;
memset(pNew, 0, sizeof(*pNew));
@@ -236508,7 +246923,7 @@ static int stmtDisconnect(sqlcipher_sqlite3_vtab *pVtab){
*/
static int stmtOpen(sqlcipher_sqlite3_vtab *p, sqlcipher_sqlite3_vtab_cursor **ppCursor){
stmt_cursor *pCur;
- pCur = sqlcipher_sqlite3_malloc( sizeof(*pCur) );
+ pCur = sqlcipher_sqlite3_malloc64( sizeof(*pCur) );
if( pCur==0 ) return SQLITE_NOMEM;
memset(pCur, 0, sizeof(*pCur));
pCur->db = ((stmt_vtab*)p)->db;
@@ -236516,10 +246931,21 @@ static int stmtOpen(sqlcipher_sqlite3_vtab *p, sqlcipher_sqlite3_vtab_cursor **p
return SQLITE_OK;
}
+static void stmtCsrReset(stmt_cursor *pCur){
+ StmtRow *pRow = 0;
+ StmtRow *pNext = 0;
+ for(pRow=pCur->pRow; pRow; pRow=pNext){
+ pNext = pRow->pNext;
+ sqlcipher_sqlite3_free(pRow);
+ }
+ pCur->pRow = 0;
+}
+
/*
** Destructor for a stmt_cursor.
*/
static int stmtClose(sqlcipher_sqlite3_vtab_cursor *cur){
+ stmtCsrReset((stmt_cursor*)cur);
sqlcipher_sqlite3_free(cur);
return SQLITE_OK;
}
@@ -236530,8 +246956,9 @@ static int stmtClose(sqlcipher_sqlite3_vtab_cursor *cur){
*/
static int stmtNext(sqlcipher_sqlite3_vtab_cursor *cur){
stmt_cursor *pCur = (stmt_cursor*)cur;
- pCur->iRowid++;
- pCur->pStmt = sqlcipher_sqlite3_next_stmt(pCur->db, pCur->pStmt);
+ StmtRow *pNext = pCur->pRow->pNext;
+ sqlcipher_sqlite3_free(pCur->pRow);
+ pCur->pRow = pNext;
return SQLITE_OK;
}
@@ -236545,39 +246972,11 @@ static int stmtColumn(
int i /* Which column to return */
){
stmt_cursor *pCur = (stmt_cursor*)cur;
- switch( i ){
- case STMT_COLUMN_SQL: {
- sqlcipher_sqlite3_result_text(ctx, sqlcipher_sqlite3_sql(pCur->pStmt), -1, SQLITE_TRANSIENT);
- break;
- }
- case STMT_COLUMN_NCOL: {
- sqlcipher_sqlite3_result_int(ctx, sqlcipher_sqlite3_column_count(pCur->pStmt));
- break;
- }
- case STMT_COLUMN_RO: {
- sqlcipher_sqlite3_result_int(ctx, sqlcipher_sqlite3_stmt_readonly(pCur->pStmt));
- break;
- }
- case STMT_COLUMN_BUSY: {
- sqlcipher_sqlite3_result_int(ctx, sqlcipher_sqlite3_stmt_busy(pCur->pStmt));
- break;
- }
- default: {
- assert( i==STMT_COLUMN_MEM );
- i = SQLITE_STMTSTATUS_MEMUSED +
- STMT_COLUMN_NSCAN - SQLITE_STMTSTATUS_FULLSCAN_STEP;
- /* Fall thru */
- }
- case STMT_COLUMN_NSCAN:
- case STMT_COLUMN_NSORT:
- case STMT_COLUMN_NAIDX:
- case STMT_COLUMN_NSTEP:
- case STMT_COLUMN_REPREP:
- case STMT_COLUMN_RUN: {
- sqlcipher_sqlite3_result_int(ctx, sqlcipher_sqlite3_stmt_status(pCur->pStmt,
- i-STMT_COLUMN_NSCAN+SQLITE_STMTSTATUS_FULLSCAN_STEP, 0));
- break;
- }
+ StmtRow *pRow = pCur->pRow;
+ if( i==STMT_COLUMN_SQL ){
+ sqlcipher_sqlite3_result_text(ctx, pRow->zSql, -1, SQLITE_TRANSIENT);
+ }else{
+ sqlcipher_sqlite3_result_int(ctx, pRow->aCol[i]);
}
return SQLITE_OK;
}
@@ -236588,7 +246987,7 @@ static int stmtColumn(
*/
static int stmtRowid(sqlcipher_sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
stmt_cursor *pCur = (stmt_cursor*)cur;
- *pRowid = pCur->iRowid;
+ *pRowid = pCur->pRow->iRowid;
return SQLITE_OK;
}
@@ -236598,7 +246997,7 @@ static int stmtRowid(sqlcipher_sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
*/
static int stmtEof(sqlcipher_sqlite3_vtab_cursor *cur){
stmt_cursor *pCur = (stmt_cursor*)cur;
- return pCur->pStmt==0;
+ return pCur->pRow==0;
}
/*
@@ -236613,9 +247012,53 @@ static int stmtFilter(
int argc, sqlcipher_sqlite3_value **argv
){
stmt_cursor *pCur = (stmt_cursor *)pVtabCursor;
- pCur->pStmt = 0;
- pCur->iRowid = 0;
- return stmtNext(pVtabCursor);
+ sqlcipher_sqlite3_stmt *p = 0;
+ sqlcipher_sqlite3_int64 iRowid = 1;
+ StmtRow **ppRow = 0;
+
+ stmtCsrReset(pCur);
+ ppRow = &pCur->pRow;
+ for(p=sqlcipher_sqlite3_next_stmt(pCur->db, 0); p; p=sqlcipher_sqlite3_next_stmt(pCur->db, p)){
+ const char *zSql = sqlcipher_sqlite3_sql(p);
+ sqlcipher_sqlite3_int64 nSql = zSql ? strlen(zSql)+1 : 0;
+ StmtRow *pNew = (StmtRow*)sqlcipher_sqlite3_malloc64(sizeof(StmtRow) + nSql);
+
+ if( pNew==0 ) return SQLITE_NOMEM;
+ memset(pNew, 0, sizeof(StmtRow));
+ if( zSql ){
+ pNew->zSql = (char*)&pNew[1];
+ memcpy(pNew->zSql, zSql, nSql);
+ }
+ pNew->aCol[STMT_COLUMN_NCOL] = sqlcipher_sqlite3_column_count(p);
+ pNew->aCol[STMT_COLUMN_RO] = sqlcipher_sqlite3_stmt_readonly(p);
+ pNew->aCol[STMT_COLUMN_BUSY] = sqlcipher_sqlite3_stmt_busy(p);
+ pNew->aCol[STMT_COLUMN_NSCAN] = sqlcipher_sqlite3_stmt_status(
+ p, SQLITE_STMTSTATUS_FULLSCAN_STEP, 0
+ );
+ pNew->aCol[STMT_COLUMN_NSORT] = sqlcipher_sqlite3_stmt_status(
+ p, SQLITE_STMTSTATUS_SORT, 0
+ );
+ pNew->aCol[STMT_COLUMN_NAIDX] = sqlcipher_sqlite3_stmt_status(
+ p, SQLITE_STMTSTATUS_AUTOINDEX, 0
+ );
+ pNew->aCol[STMT_COLUMN_NSTEP] = sqlcipher_sqlite3_stmt_status(
+ p, SQLITE_STMTSTATUS_VM_STEP, 0
+ );
+ pNew->aCol[STMT_COLUMN_REPREP] = sqlcipher_sqlite3_stmt_status(
+ p, SQLITE_STMTSTATUS_REPREPARE, 0
+ );
+ pNew->aCol[STMT_COLUMN_RUN] = sqlcipher_sqlite3_stmt_status(
+ p, SQLITE_STMTSTATUS_RUN, 0
+ );
+ pNew->aCol[STMT_COLUMN_MEM] = sqlcipher_sqlite3_stmt_status(
+ p, SQLITE_STMTSTATUS_MEMUSED, 0
+ );
+ pNew->iRowid = iRowid++;
+ *ppRow = pNew;
+ ppRow = &pNew->pNext;
+ }
+
+ return SQLITE_OK;
}
/*
@@ -236694,10 +247137,6 @@ SQLITE_API int sqlcipher_sqlite3_stmt_init(
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */
/************** End of stmt.c ************************************************/
-#if __LINE__!=236697
-#undef SQLITE_SOURCE_ID
-#define SQLITE_SOURCE_ID "2021-01-20 14:10:07 10e20c0b43500cfb9bbc0eaa061c57514f715d87238f4d835880cd846b9ealt2"
-#endif
/* Return the source-id for this library */
SQLITE_API const char *sqlcipher_sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
/************************** End of sqlcipher_sqlite3.c ******************************/
diff --git a/Plugins/DbSqliteCipher/sqlcipher.h b/Plugins/DbSqliteCipher/sqlcipher.h
index 08260ac..0cda434 100644
--- a/Plugins/DbSqliteCipher/sqlcipher.h
+++ b/Plugins/DbSqliteCipher/sqlcipher.h
@@ -43,7 +43,30 @@ extern "C" {
/*
-** Provide the ability to override linkage features of the interface.
+** Facilitate override of interface linkage and calling conventions.
+** Be aware that these macros may not be used within this particular
+** translation of the amalgamation and its associated header file.
+**
+** The SQLITE_EXTERN and SQLITE_API macros are used to instruct the
+** compiler that the target identifier should have external linkage.
+**
+** The SQLITE_CDECL macro is used to set the calling convention for
+** public functions that accept a variable number of arguments.
+**
+** The SQLITE_APICALL macro is used to set the calling convention for
+** public functions that accept a fixed number of arguments.
+**
+** The SQLITE_STDCALL macro is no longer used and is now deprecated.
+**
+** The SQLITE_CALLBACK macro is used to set the calling convention for
+** function pointers.
+**
+** The SQLITE_SYSAPI macro is used to set the calling convention for
+** functions provided by the operating system.
+**
+** Currently, the SQLITE_CDECL, SQLITE_APICALL, SQLITE_CALLBACK, and
+** SQLITE_SYSAPI macros are used only when building for environments
+** that require non-default calling conventions.
*/
#ifndef SQLITE_EXTERN
# define SQLITE_EXTERN extern
@@ -123,9 +146,9 @@ extern "C" {
** [sqlcipher_sqlite3_libversion_number()], [sqlcipher_sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-#define SQLITE_VERSION "3.34.1"
-#define SQLITE_VERSION_NUMBER 3034001
-#define SQLITE_SOURCE_ID "2021-01-20 14:10:07 10e20c0b43500cfb9bbc0eaa061c57514f715d87238f4d835880cd846b9ealt1"
+#define SQLITE_VERSION "3.39.4"
+#define SQLITE_VERSION_NUMBER 3039004
+#define SQLITE_SOURCE_ID "2022-09-29 15:55:41 a29f9949895322123f7c38fbe94c649a9d6e6c9cd0c3b41c96d694552f26alt1"
/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -537,12 +560,13 @@ SQLITE_API int sqlcipher_sqlite3_exec(
#define SQLITE_CONSTRAINT_VTAB (SQLITE_CONSTRAINT | (9<<8))
#define SQLITE_CONSTRAINT_ROWID (SQLITE_CONSTRAINT |(10<<8))
#define SQLITE_CONSTRAINT_PINNED (SQLITE_CONSTRAINT |(11<<8))
+#define SQLITE_CONSTRAINT_DATATYPE (SQLITE_CONSTRAINT |(12<<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))
#define SQLITE_AUTH_USER (SQLITE_AUTH | (1<<8))
#define SQLITE_OK_LOAD_PERMANENTLY (SQLITE_OK | (1<<8))
-#define SQLITE_OK_SYMLINK (SQLITE_OK | (2<<8))
+#define SQLITE_OK_SYMLINK (SQLITE_OK | (2<<8)) /* internal use only */
/*
** CAPI3REF: Flags For File Open Operations
@@ -550,6 +574,19 @@ SQLITE_API int sqlcipher_sqlite3_exec(
** These bit values are intended for use in the
** 3rd parameter to the [sqlcipher_sqlite3_open_v2()] interface and
** in the 4th parameter to the [sqlcipher_sqlite3_vfs.xOpen] method.
+**
+** Only those flags marked as "Ok for sqlcipher_sqlite3_open_v2()" may be
+** used as the third argument to the [sqlcipher_sqlite3_open_v2()] interface.
+** The other flags have historically been ignored by sqlcipher_sqlite3_open_v2(),
+** though future versions of SQLite might change so that an error is
+** raised if any of the disallowed bits are passed into sqlcipher_sqlite3_open_v2().
+** Applications should not depend on the historical behavior.
+**
+** Note in particular that passing the SQLITE_OPEN_EXCLUSIVE flag into
+** [sqlcipher_sqlite3_open_v2()] does *not* cause the underlying database file
+** to be opened using O_EXCL. Passing SQLITE_OPEN_EXCLUSIVE into
+** [sqlcipher_sqlite3_open_v2()] has historically be a no-op and might become an
+** error in future versions of SQLite.
*/
#define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlcipher_sqlite3_open_v2() */
#define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlcipher_sqlite3_open_v2() */
@@ -572,6 +609,7 @@ SQLITE_API int sqlcipher_sqlite3_exec(
#define SQLITE_OPEN_PRIVATECACHE 0x00040000 /* Ok for sqlcipher_sqlite3_open_v2() */
#define SQLITE_OPEN_WAL 0x00080000 /* VFS only */
#define SQLITE_OPEN_NOFOLLOW 0x01000000 /* Ok for sqlcipher_sqlite3_open_v2() */
+#define SQLITE_OPEN_EXRESCODE 0x02000000 /* Extended result codes */
/* Reserved: 0x00F00000 */
/* Legacy compatibility: */
@@ -1128,6 +1166,23 @@ struct sqlcipher_sqlite3_io_methods {
** file to the database file, but before the *-shm file is updated to
** record the fact that the pages have been checkpointed.
** </ul>
+**
+** <li>[[SQLITE_FCNTL_EXTERNAL_READER]]
+** The EXPERIMENTAL [SQLITE_FCNTL_EXTERNAL_READER] opcode is used to detect
+** whether or not there is a database client in another process with a wal-mode
+** transaction open on the database or not. It is only available on unix.The
+** (void*) argument passed with this file-control should be a pointer to a
+** value of type (int). The integer value is set to 1 if the database is a wal
+** mode database and there exists at least one client in another process that
+** currently has an SQL transaction open on the database. It is set to 0 if
+** the database is not a wal-mode db, or if there is no such connection in any
+** other process. This opcode cannot be used to detect transactions opened
+** by clients within the current process, only within other processes.
+** </ul>
+**
+** <li>[[SQLITE_FCNTL_CKSM_FILE]]
+** Used by the cksmvfs VFS module only.
+** </ul>
*/
#define SQLITE_FCNTL_LOCKSTATE 1
#define SQLITE_FCNTL_GET_LOCKPROXYFILE 2
@@ -1167,6 +1222,8 @@ struct sqlcipher_sqlite3_io_methods {
#define SQLITE_FCNTL_CKPT_DONE 37
#define SQLITE_FCNTL_RESERVE_BYTES 38
#define SQLITE_FCNTL_CKPT_START 39
+#define SQLITE_FCNTL_EXTERNAL_READER 40
+#define SQLITE_FCNTL_CKSM_FILE 41
/* deprecated names */
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
@@ -2115,7 +2172,13 @@ struct sqlcipher_sqlite3_mem_methods {
** The second parameter is a pointer to an integer into which
** is written 0 or 1 to indicate whether triggers are disabled or enabled
** following this call. The second parameter may be a NULL pointer, in
-** which case the trigger setting is not reported back. </dd>
+** which case the trigger setting is not reported back.
+**
+** <p>Originally this option disabled all triggers. ^(However, since
+** SQLite version 3.35.0, TEMP triggers are still allowed even if
+** this option is off. So, in other words, this option now only disables
+** triggers in the main database schema or in the schemas of ATTACH-ed
+** databases.)^ </dd>
**
** [[SQLITE_DBCONFIG_ENABLE_VIEW]]
** <dt>SQLITE_DBCONFIG_ENABLE_VIEW</dt>
@@ -2126,7 +2189,13 @@ struct sqlcipher_sqlite3_mem_methods {
** The second parameter is a pointer to an integer into which
** is written 0 or 1 to indicate whether views are disabled or enabled
** following this call. The second parameter may be a NULL pointer, in
-** which case the view setting is not reported back. </dd>
+** which case the view setting is not reported back.
+**
+** <p>Originally this option disabled all views. ^(However, since
+** SQLite version 3.35.0, TEMP views are still allowed even if
+** this option is off. So, in other words, this option now only disables
+** views in the main database schema or in the schemas of ATTACH-ed
+** databases.)^ </dd>
**
** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]]
** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt>
@@ -2433,11 +2502,14 @@ SQLITE_API void sqlcipher_sqlite3_set_last_insert_rowid(sqlcipher_sqlite3*,sqlci
** CAPI3REF: Count The Number Of Rows Modified
** METHOD: sqlcipher_sqlite3
**
-** ^This function returns the number of rows modified, inserted or
+** ^These functions return the number of rows modified, inserted or
** deleted by the most recently completed INSERT, UPDATE or DELETE
** statement on the database connection specified by the only parameter.
-** ^Executing any other type of SQL statement does not modify the value
-** returned by this function.
+** The two functions are identical except for the type of the return value
+** and that if the number of rows modified by the most recent INSERT, UPDATE
+** or DELETE is greater than the maximum value supported by type "int", then
+** the return value of sqlcipher_sqlite3_changes() is undefined. ^Executing any other
+** type of SQL statement does not modify the value returned by these functions.
**
** ^Only changes made directly by the INSERT, UPDATE or DELETE statement are
** considered - auxiliary changes caused by [CREATE TRIGGER | triggers],
@@ -2486,16 +2558,21 @@ SQLITE_API void sqlcipher_sqlite3_set_last_insert_rowid(sqlcipher_sqlite3*,sqlci
** </ul>
*/
SQLITE_API int sqlcipher_sqlite3_changes(sqlcipher_sqlite3*);
+SQLITE_API sqlcipher_sqlite3_int64 sqlcipher_sqlite3_changes64(sqlcipher_sqlite3*);
/*
** CAPI3REF: Total Number Of Rows Modified
** METHOD: sqlcipher_sqlite3
**
-** ^This function returns the total number of rows inserted, modified or
+** ^These functions return the total number of rows inserted, modified or
** deleted by all [INSERT], [UPDATE] or [DELETE] statements completed
** since the database connection was opened, including those executed as
-** part of trigger programs. ^Executing any other type of SQL statement
-** does not affect the value returned by sqlcipher_sqlite3_total_changes().
+** part of trigger programs. The two functions are identical except for the
+** type of the return value and that if the number of rows modified by the
+** connection exceeds the maximum value supported by type "int", then
+** the return value of sqlcipher_sqlite3_total_changes() is undefined. ^Executing
+** any other type of SQL statement does not affect the value returned by
+** sqlcipher_sqlite3_total_changes().
**
** ^Changes made as part of [foreign key actions] are included in the
** count, but those made as part of REPLACE constraint resolution are
@@ -2523,6 +2600,7 @@ SQLITE_API int sqlcipher_sqlite3_changes(sqlcipher_sqlite3*);
** </ul>
*/
SQLITE_API int sqlcipher_sqlite3_total_changes(sqlcipher_sqlite3*);
+SQLITE_API sqlcipher_sqlite3_int64 sqlcipher_sqlite3_total_changes64(sqlcipher_sqlite3*);
/*
** CAPI3REF: Interrupt A Long-Running Query
@@ -3352,6 +3430,14 @@ SQLITE_API void sqlcipher_sqlite3_progress_handler(sqlcipher_sqlite3*, int, int(
** the default shared cache setting provided by
** [sqlcipher_sqlite3_enable_shared_cache()].)^
**
+** [[OPEN_EXRESCODE]] ^(<dt>[SQLITE_OPEN_EXRESCODE]</dt>
+** <dd>The database connection comes up in "extended result code mode".
+** In other words, the database behaves has if
+** [sqlcipher_sqlite3_extended_result_codes(db,1)] where called on the database
+** connection as soon as the connection is created. In addition to setting
+** the extended result code mode, this flag also causes [sqlcipher_sqlite3_open_v2()]
+** to return an extended result code.</dd>
+**
** [[OPEN_NOFOLLOW]] ^(<dt>[SQLITE_OPEN_NOFOLLOW]</dt>
** <dd>The database filename is not allowed to be a symbolic link</dd>
** </dl>)^
@@ -3359,7 +3445,15 @@ SQLITE_API void sqlcipher_sqlite3_progress_handler(sqlcipher_sqlite3*, int, int(
** If the 3rd parameter to sqlcipher_sqlite3_open_v2() is not one of the
** required combinations shown above optionally combined with other
** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits]
-** then the behavior is undefined.
+** then the behavior is undefined. Historic versions of SQLite
+** have silently ignored surplus bits in the flags parameter to
+** sqlcipher_sqlite3_open_v2(), however that behavior might not be carried through
+** into future versions of SQLite and so applications should not rely
+** upon it. Note in particular that the SQLITE_OPEN_EXCLUSIVE flag is a no-op
+** for sqlcipher_sqlite3_open_v2(). The SQLITE_OPEN_EXCLUSIVE does *not* cause
+** the open to fail if the database already exists. The SQLITE_OPEN_EXCLUSIVE
+** flag is intended for use by the [sqlcipher_sqlite3_vfs|VFS interface] only, and not
+** by sqlcipher_sqlite3_open_v2().
**
** ^The fourth parameter to sqlcipher_sqlite3_open_v2() is the name of the
** [sqlcipher_sqlite3_vfs] object that defines the operating system interface that
@@ -3499,6 +3593,7 @@ SQLITE_API void sqlcipher_sqlite3_progress_handler(sqlcipher_sqlite3*, int, int(
** 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.
+** Use "ro" instead: "file:data.db?mode=ro".
** </table>
**
** ^URI hexadecimal escape sequences (%HH) are supported within the path and
@@ -3729,13 +3824,14 @@ SQLITE_API void sqlcipher_sqlite3_free_filename(char*);
** sqlcipher_sqlite3_extended_errcode() might change with each API call.
** Except, there are some interfaces that are guaranteed to never
** change the value of the error code. The error-code preserving
-** interfaces are:
+** interfaces include the following:
**
** <ul>
** <li> sqlcipher_sqlite3_errcode()
** <li> sqlcipher_sqlite3_extended_errcode()
** <li> sqlcipher_sqlite3_errmsg()
** <li> sqlcipher_sqlite3_errmsg16()
+** <li> sqlcipher_sqlite3_error_offset()
** </ul>
**
** ^The sqlcipher_sqlite3_errmsg() and sqlcipher_sqlite3_errmsg16() return English-language
@@ -3750,6 +3846,13 @@ SQLITE_API void sqlcipher_sqlite3_free_filename(char*);
** ^(Memory to hold the error message string is managed internally
** and must not be freed by the application)^.
**
+** ^If the most recent error references a specific token in the input
+** SQL, the sqlcipher_sqlite3_error_offset() interface returns the byte offset
+** of the start of that token. ^The byte offset returned by
+** sqlcipher_sqlite3_error_offset() assumes that the input SQL is UTF8.
+** ^If the most recent error does not reference a specific token in the input
+** SQL, then the sqlcipher_sqlite3_error_offset() function returns -1.
+**
** 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.
@@ -3769,6 +3872,7 @@ SQLITE_API int sqlcipher_sqlite3_extended_errcode(sqlcipher_sqlite3 *db);
SQLITE_API const char *sqlcipher_sqlite3_errmsg(sqlcipher_sqlite3*);
SQLITE_API const void *sqlcipher_sqlite3_errmsg16(sqlcipher_sqlite3*);
SQLITE_API const char *sqlcipher_sqlite3_errstr(int);
+SQLITE_API int sqlcipher_sqlite3_error_offset(sqlcipher_sqlite3 *db);
/*
** CAPI3REF: Prepared Statement Object
@@ -4126,12 +4230,17 @@ SQLITE_API int sqlcipher_sqlite3_prepare16_v3(
** are managed by SQLite and are automatically freed when the prepared
** statement is finalized.
** ^The string returned by sqlcipher_sqlite3_expanded_sql(P), on the other hand,
-** is obtained from [sqlcipher_sqlite3_malloc()] and must be free by the application
+** is obtained from [sqlcipher_sqlite3_malloc()] and must be freed by the application
** by passing it to [sqlcipher_sqlite3_free()].
+**
+** ^The sqlcipher_sqlite3_normalized_sql() interface is only available if
+** the [SQLITE_ENABLE_NORMALIZE] compile-time option is defined.
*/
SQLITE_API const char *sqlcipher_sqlite3_sql(sqlcipher_sqlite3_stmt *pStmt);
SQLITE_API char *sqlcipher_sqlite3_expanded_sql(sqlcipher_sqlite3_stmt *pStmt);
+#ifdef SQLITE_ENABLE_NORMALIZE
SQLITE_API const char *sqlcipher_sqlite3_normalized_sql(sqlcipher_sqlite3_stmt *pStmt);
+#endif
/*
** CAPI3REF: Determine If An SQL Statement Writes The Database
@@ -4166,6 +4275,19 @@ SQLITE_API const char *sqlcipher_sqlite3_normalized_sql(sqlcipher_sqlite3_stmt *
** [BEGIN] merely sets internal flags, but the [BEGIN|BEGIN IMMEDIATE] and
** [BEGIN|BEGIN EXCLUSIVE] commands do touch the database and so
** sqlcipher_sqlite3_stmt_readonly() returns false for those commands.
+**
+** ^This routine returns false if there is any possibility that the
+** statement might change the database file. ^A false return does
+** not guarantee that the statement will change the database file.
+** ^For example, an UPDATE statement might have a WHERE clause that
+** makes it a no-op, but the sqlcipher_sqlite3_stmt_readonly() result would still
+** be false. ^Similarly, a CREATE TABLE IF NOT EXISTS statement is a
+** read-only no-op if the table already exists, but
+** sqlcipher_sqlite3_stmt_readonly() still returns false for such a statement.
+**
+** ^If prepared statement X is an [EXPLAIN] or [EXPLAIN QUERY PLAN]
+** statement, then sqlcipher_sqlite3_stmt_readonly(X) returns the same value as
+** if the EXPLAIN or EXPLAIN QUERY PLAN prefix were omitted.
*/
SQLITE_API int sqlcipher_sqlite3_stmt_readonly(sqlcipher_sqlite3_stmt *pStmt);
@@ -4234,6 +4356,8 @@ SQLITE_API int sqlcipher_sqlite3_stmt_busy(sqlcipher_sqlite3_stmt*);
**
** ^The sqlcipher_sqlite3_value objects that are passed as parameters into the
** implementation of [application-defined SQL functions] are protected.
+** ^The sqlcipher_sqlite3_value objects returned by [sqlcipher_sqlite3_vtab_rhs_value()]
+** are protected.
** ^The sqlcipher_sqlite3_value object returned by
** [sqlcipher_sqlite3_column_value()] is unprotected.
** Unprotected sqlcipher_sqlite3_value objects may only be used as arguments
@@ -4335,18 +4459,22 @@ typedef struct sqlcipher_sqlite3_context sqlcipher_sqlite3_context;
** contain embedded NULs. The result of expressions involving strings
** with embedded NULs is undefined.
**
-** ^The fifth argument to the BLOB and string binding interfaces
-** is a destructor used to dispose of the BLOB or
-** string after SQLite has finished with it. ^The destructor is called
-** to dispose of the BLOB or string even if the call to the bind API fails,
-** except the destructor is not called if the third parameter is a NULL
-** pointer or the fourth parameter is negative.
-** ^If the fifth argument is
-** the special value [SQLITE_STATIC], then SQLite assumes that the
-** information is in static, unmanaged space and does not need to be freed.
-** ^If the fifth argument has the value [SQLITE_TRANSIENT], then
-** SQLite makes its own private copy of the data immediately, before
-** the sqlcipher_sqlite3_bind_*() routine returns.
+** ^The fifth argument to the BLOB and string binding interfaces controls
+** or indicates the lifetime of the object referenced by the third parameter.
+** These three options exist:
+** ^ (1) A destructor to dispose of the BLOB or string after SQLite has finished
+** with it may be passed. ^It is called to dispose of the BLOB or string even
+** if the call to the bind API fails, except the destructor is not called if
+** the third parameter is a NULL pointer or the fourth parameter is negative.
+** ^ (2) The special constant, [SQLITE_STATIC], may be passsed to indicate that
+** the application remains responsible for disposing of the object. ^In this
+** case, the object and the provided pointer to it must remain valid until
+** either the prepared statement is finalized or the same SQL parameter is
+** bound to something else, whichever occurs sooner.
+** ^ (3) The constant, [SQLITE_TRANSIENT], may be passed to indicate that the
+** object is to be copied prior to the return from sqlcipher_sqlite3_bind_*(). ^The
+** object and pointer to it must remain valid until then. ^SQLite will then
+** manage the lifetime of its private copy.
**
** ^The sixth argument to sqlcipher_sqlite3_bind_text64() must be one of
** [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE]
@@ -4851,6 +4979,10 @@ SQLITE_API int sqlcipher_sqlite3_data_count(sqlcipher_sqlite3_stmt *pStmt);
** even empty strings, are always zero-terminated. ^The return
** value from sqlcipher_sqlite3_column_blob() for a zero-length BLOB is a NULL pointer.
**
+** ^Strings returned by sqlcipher_sqlite3_column_text16() always have the endianness
+** which is native to the platform, regardless of the text encoding set
+** for the database.
+**
** <b>Warning:</b> ^The object returned by [sqlcipher_sqlite3_column_value()] is an
** [unprotected sqlcipher_sqlite3_value] object. In a multithreaded environment,
** an unprotected sqlcipher_sqlite3_value object may only be used safely with
@@ -4864,7 +4996,7 @@ SQLITE_API int sqlcipher_sqlite3_data_count(sqlcipher_sqlite3_stmt *pStmt);
** [application-defined SQL functions] or [virtual tables], not within
** top-level application code.
**
-** The these routines may attempt to convert the datatype of the result.
+** These routines may attempt to convert the datatype of the result.
** ^For example, if the internal representation is FLOAT and a text result
** is requested, [sqlcipher_sqlite3_snprintf()] is used internally to perform the
** conversion automatically. ^(The following table details the conversions
@@ -4889,7 +5021,7 @@ SQLITE_API int sqlcipher_sqlite3_data_count(sqlcipher_sqlite3_stmt *pStmt);
** <tr><td> TEXT <td> BLOB <td> No change
** <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
+** <tr><td> BLOB <td> TEXT <td> [CAST] to TEXT, ensure zero terminator
** </table>
** </blockquote>)^
**
@@ -5088,7 +5220,6 @@ SQLITE_API int sqlcipher_sqlite3_reset(sqlcipher_sqlite3_stmt *pStmt);
** within VIEWs, TRIGGERs, CHECK constraints, generated column expressions,
** index expressions, or the WHERE clause of partial indexes.
**
-** <span style="background-color:#ffff90;">
** For best security, the [SQLITE_DIRECTONLY] flag is recommended for
** all application-defined SQL functions that do not need to be
** used inside of triggers, view, CHECK constraints, or other elements of
@@ -5098,7 +5229,6 @@ SQLITE_API int sqlcipher_sqlite3_reset(sqlcipher_sqlite3_stmt *pStmt);
** a database file to include invocations of the function with parameters
** chosen by the attacker, which the application will then execute when
** the database file is opened and read.
-** </span>
**
** ^(The fifth parameter is an arbitrary pointer. The implementation of the
** function can gain access to this pointer using [sqlcipher_sqlite3_user_data()].)^
@@ -5463,7 +5593,8 @@ SQLITE_API unsigned int sqlcipher_sqlite3_value_subtype(sqlcipher_sqlite3_value*
** object D and returns a pointer to that copy. ^The [sqlcipher_sqlite3_value] returned
** is a [protected sqlcipher_sqlite3_value] object even if the input is not.
** ^The sqlcipher_sqlite3_value_dup(V) interface returns NULL if V is NULL or if a
-** memory allocation fails.
+** memory allocation fails. ^If V is a [pointer value], then the result
+** of sqlcipher_sqlite3_value_dup(V) is a NULL value.
**
** ^The sqlcipher_sqlite3_value_free(V) interface frees an [sqlcipher_sqlite3_value] object
** previously obtained from [sqlcipher_sqlite3_value_dup()]. ^If V is a NULL pointer
@@ -5976,6 +6107,19 @@ SQLITE_API int sqlcipher_sqlite3_key_v2(
** The code to implement this API is not available in the public release
** of SQLite.
*/
+/* SQLCipher usage note:
+
+ If the current database is plaintext SQLCipher will NOT encrypt it.
+ If the current database is encrypted and pNew==0 or nNew==0, SQLCipher
+ will NOT decrypt it.
+
+ This routine will ONLY work on an already encrypted database in order
+ to change the key.
+
+ Conversion from plaintext-to-encrypted or encrypted-to-plaintext should
+ use an ATTACHed database and the sqlcipher_export() convenience function
+ as per the SQLCipher Documentation.
+*/
SQLITE_API int sqlcipher_sqlite3_rekey(
sqlcipher_sqlite3 *db, /* Database to be rekeyed */
const void *pKey, int nKey /* The new key */
@@ -6193,6 +6337,28 @@ SQLITE_API int sqlcipher_sqlite3_get_autocommit(sqlcipher_sqlite3*);
SQLITE_API sqlcipher_sqlite3 *sqlcipher_sqlite3_db_handle(sqlcipher_sqlite3_stmt*);
/*
+** CAPI3REF: Return The Schema Name For A Database Connection
+** METHOD: sqlcipher_sqlite3
+**
+** ^The sqlcipher_sqlite3_db_name(D,N) interface returns a pointer to the schema name
+** for the N-th database on database connection D, or a NULL pointer of N is
+** out of range. An N value of 0 means the main database file. An N of 1 is
+** the "temp" schema. Larger values of N correspond to various ATTACH-ed
+** databases.
+**
+** Space to hold the string that is returned by sqlcipher_sqlite3_db_name() is managed
+** by SQLite itself. The string might be deallocated by any operation that
+** changes the schema, including [ATTACH] or [DETACH] or calls to
+** [sqlcipher_sqlite3_serialize()] or [sqlcipher_sqlite3_deserialize()], even operations that
+** occur on a different thread. Applications that need to
+** remember the string long-term should make their own copy. Applications that
+** are accessing the same database connection simultaneously on multiple
+** threads should mutex-protect calls to this API and should make their own
+** private copy of the result prior to releasing the mutex.
+*/
+SQLITE_API const char *sqlcipher_sqlite3_db_name(sqlcipher_sqlite3 *db, int N);
+
+/*
** CAPI3REF: Return The Filename For A Database Connection
** METHOD: sqlcipher_sqlite3
**
@@ -6352,6 +6518,72 @@ SQLITE_API void *sqlcipher_sqlite3_commit_hook(sqlcipher_sqlite3*, int(*)(void*)
SQLITE_API void *sqlcipher_sqlite3_rollback_hook(sqlcipher_sqlite3*, void(*)(void *), void*);
/*
+** CAPI3REF: Autovacuum Compaction Amount Callback
+** METHOD: sqlcipher_sqlite3
+**
+** ^The sqlcipher_sqlite3_autovacuum_pages(D,C,P,X) interface registers a callback
+** function C that is invoked prior to each autovacuum of the database
+** file. ^The callback is passed a copy of the generic data pointer (P),
+** the schema-name of the attached database that is being autovacuumed,
+** the the size of the database file in pages, the number of free pages,
+** and the number of bytes per page, respectively. The callback should
+** return the number of free pages that should be removed by the
+** autovacuum. ^If the callback returns zero, then no autovacuum happens.
+** ^If the value returned is greater than or equal to the number of
+** free pages, then a complete autovacuum happens.
+**
+** <p>^If there are multiple ATTACH-ed database files that are being
+** modified as part of a transaction commit, then the autovacuum pages
+** callback is invoked separately for each file.
+**
+** <p><b>The callback is not reentrant.</b> The callback function should
+** not attempt to invoke any other SQLite interface. If it does, bad
+** things may happen, including segmentation faults and corrupt database
+** files. The callback function should be a simple function that
+** does some arithmetic on its input parameters and returns a result.
+**
+** ^The X parameter to sqlcipher_sqlite3_autovacuum_pages(D,C,P,X) is an optional
+** destructor for the P parameter. ^If X is not NULL, then X(P) is
+** invoked whenever the database connection closes or when the callback
+** is overwritten by another invocation of sqlcipher_sqlite3_autovacuum_pages().
+**
+** <p>^There is only one autovacuum pages callback per database connection.
+** ^Each call to the sqlcipher_sqlite3_autovacuum_pages() interface overrides all
+** previous invocations for that database connection. ^If the callback
+** argument (C) to sqlcipher_sqlite3_autovacuum_pages(D,C,P,X) is a NULL pointer,
+** then the autovacuum steps callback is cancelled. The return value
+** from sqlcipher_sqlite3_autovacuum_pages() is normally SQLITE_OK, but might
+** be some other error code if something goes wrong. The current
+** implementation will only return SQLITE_OK or SQLITE_MISUSE, but other
+** return codes might be added in future releases.
+**
+** <p>If no autovacuum pages callback is specified (the usual case) or
+** a NULL pointer is provided for the callback,
+** then the default behavior is to vacuum all free pages. So, in other
+** words, the default behavior is the same as if the callback function
+** were something like this:
+**
+** <blockquote><pre>
+** &nbsp; unsigned int demonstration_autovac_pages_callback(
+** &nbsp; void *pClientData,
+** &nbsp; const char *zSchema,
+** &nbsp; unsigned int nDbPage,
+** &nbsp; unsigned int nFreePage,
+** &nbsp; unsigned int nBytePerPage
+** &nbsp; ){
+** &nbsp; return nFreePage;
+** &nbsp; }
+** </pre></blockquote>
+*/
+SQLITE_API int sqlcipher_sqlite3_autovacuum_pages(
+ sqlcipher_sqlite3 *db,
+ unsigned int(*)(void*,const char*,unsigned int,unsigned int,unsigned int),
+ void*,
+ void(*)(void*)
+);
+
+
+/*
** CAPI3REF: Data Change Notification Callbacks
** METHOD: sqlcipher_sqlite3
**
@@ -6992,24 +7224,56 @@ struct sqlcipher_sqlite3_index_info {
**
** These macros define the allowed values for the
** [sqlcipher_sqlite3_index_info].aConstraint[].op field. Each value represents
-** an operator that is part of a constraint term in the wHERE clause of
+** an operator that is part of a constraint term in the WHERE clause of
** a query that uses a [virtual table].
-*/
-#define SQLITE_INDEX_CONSTRAINT_EQ 2
-#define SQLITE_INDEX_CONSTRAINT_GT 4
-#define SQLITE_INDEX_CONSTRAINT_LE 8
-#define SQLITE_INDEX_CONSTRAINT_LT 16
-#define SQLITE_INDEX_CONSTRAINT_GE 32
-#define SQLITE_INDEX_CONSTRAINT_MATCH 64
-#define SQLITE_INDEX_CONSTRAINT_LIKE 65
-#define SQLITE_INDEX_CONSTRAINT_GLOB 66
-#define SQLITE_INDEX_CONSTRAINT_REGEXP 67
-#define SQLITE_INDEX_CONSTRAINT_NE 68
-#define SQLITE_INDEX_CONSTRAINT_ISNOT 69
-#define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70
-#define SQLITE_INDEX_CONSTRAINT_ISNULL 71
-#define SQLITE_INDEX_CONSTRAINT_IS 72
-#define SQLITE_INDEX_CONSTRAINT_FUNCTION 150
+**
+** ^The left-hand operand of the operator is given by the corresponding
+** aConstraint[].iColumn field. ^An iColumn of -1 indicates the left-hand
+** operand is the rowid.
+** The SQLITE_INDEX_CONSTRAINT_LIMIT and SQLITE_INDEX_CONSTRAINT_OFFSET
+** operators have no left-hand operand, and so for those operators the
+** corresponding aConstraint[].iColumn is meaningless and should not be
+** used.
+**
+** All operator values from SQLITE_INDEX_CONSTRAINT_FUNCTION through
+** value 255 are reserved to represent functions that are overloaded
+** by the [xFindFunction|xFindFunction method] of the virtual table
+** implementation.
+**
+** The right-hand operands for each constraint might be accessible using
+** the [sqlcipher_sqlite3_vtab_rhs_value()] interface. Usually the right-hand
+** operand is only available if it appears as a single constant literal
+** in the input SQL. If the right-hand operand is another column or an
+** expression (even a constant expression) or a parameter, then the
+** sqlcipher_sqlite3_vtab_rhs_value() probably will not be able to extract it.
+** ^The SQLITE_INDEX_CONSTRAINT_ISNULL and
+** SQLITE_INDEX_CONSTRAINT_ISNOTNULL operators have no right-hand operand
+** and hence calls to sqlcipher_sqlite3_vtab_rhs_value() for those operators will
+** always return SQLITE_NOTFOUND.
+**
+** The collating sequence to be used for comparison can be found using
+** the [sqlcipher_sqlite3_vtab_collation()] interface. For most real-world virtual
+** tables, the collating sequence of constraints does not matter (for example
+** because the constraints are numeric) and so the sqlcipher_sqlite3_vtab_collation()
+** interface is no commonly needed.
+*/
+#define SQLITE_INDEX_CONSTRAINT_EQ 2
+#define SQLITE_INDEX_CONSTRAINT_GT 4
+#define SQLITE_INDEX_CONSTRAINT_LE 8
+#define SQLITE_INDEX_CONSTRAINT_LT 16
+#define SQLITE_INDEX_CONSTRAINT_GE 32
+#define SQLITE_INDEX_CONSTRAINT_MATCH 64
+#define SQLITE_INDEX_CONSTRAINT_LIKE 65
+#define SQLITE_INDEX_CONSTRAINT_GLOB 66
+#define SQLITE_INDEX_CONSTRAINT_REGEXP 67
+#define SQLITE_INDEX_CONSTRAINT_NE 68
+#define SQLITE_INDEX_CONSTRAINT_ISNOT 69
+#define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70
+#define SQLITE_INDEX_CONSTRAINT_ISNULL 71
+#define SQLITE_INDEX_CONSTRAINT_IS 72
+#define SQLITE_INDEX_CONSTRAINT_LIMIT 73
+#define SQLITE_INDEX_CONSTRAINT_OFFSET 74
+#define SQLITE_INDEX_CONSTRAINT_FUNCTION 150
/*
** CAPI3REF: Register A Virtual Table Implementation
@@ -7038,7 +7302,7 @@ struct sqlcipher_sqlite3_index_info {
** destructor.
**
** ^If the third parameter (the pointer to the sqlcipher_sqlite3_module object) is
-** NULL then no new module is create and any existing modules with the
+** NULL then no new module is created and any existing modules with the
** same name are dropped.
**
** See also: [sqlcipher_sqlite3_drop_modules()]
@@ -7812,7 +8076,10 @@ SQLITE_API int sqlcipher_sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_PRNG_SEED 28
#define SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS 29
#define SQLITE_TESTCTRL_SEEK_COUNT 30
-#define SQLITE_TESTCTRL_LAST 30 /* Largest TESTCTRL */
+#define SQLITE_TESTCTRL_TRACEFLAGS 31
+#define SQLITE_TESTCTRL_TUNE 32
+#define SQLITE_TESTCTRL_LOGEST 33
+#define SQLITE_TESTCTRL_LAST 33 /* Largest TESTCTRL */
/*
** CAPI3REF: SQL Keyword Checking
@@ -8335,6 +8602,16 @@ SQLITE_API int sqlcipher_sqlite3_stmt_status(sqlcipher_sqlite3_stmt*, int op,int
** The counter is incremented on the first [sqlcipher_sqlite3_step()] call of each
** cycle.
**
+** [[SQLITE_STMTSTATUS_FILTER_MISS]]
+** [[SQLITE_STMTSTATUS_FILTER HIT]]
+** <dt>SQLITE_STMTSTATUS_FILTER_HIT<br>
+** SQLITE_STMTSTATUS_FILTER_MISS</dt>
+** <dd>^SQLITE_STMTSTATUS_FILTER_HIT is the number of times that a join
+** step was bypassed because a Bloom filter returned not-found. The
+** corresponding SQLITE_STMTSTATUS_FILTER_MISS value is the number of
+** times that the Bloom filter returned a find, and thus the join step
+** had to be processed as normal.
+**
** [[SQLITE_STMTSTATUS_MEMUSED]] <dt>SQLITE_STMTSTATUS_MEMUSED</dt>
** <dd>^This is the approximate number of bytes of heap memory
** used to store the prepared statement. ^This value is not actually
@@ -8349,6 +8626,8 @@ SQLITE_API int sqlcipher_sqlite3_stmt_status(sqlcipher_sqlite3_stmt*, int op,int
#define SQLITE_STMTSTATUS_VM_STEP 4
#define SQLITE_STMTSTATUS_REPREPARE 5
#define SQLITE_STMTSTATUS_RUN 6
+#define SQLITE_STMTSTATUS_FILTER_MISS 7
+#define SQLITE_STMTSTATUS_FILTER_HIT 8
#define SQLITE_STMTSTATUS_MEMUSED 99
/*
@@ -9012,8 +9291,9 @@ SQLITE_API void sqlcipher_sqlite3_log(int iErrCode, const char *zFormat, ...);
**
** A single database handle may have at most a single write-ahead log callback
** registered at one time. ^Calling [sqlcipher_sqlite3_wal_hook()] replaces any
-** previously registered write-ahead log callback. ^Note that the
-** [sqlcipher_sqlite3_wal_autocheckpoint()] interface and the
+** previously registered write-ahead log callback. ^The return value is
+** a copy of the third parameter from the previous call, if any, or 0.
+** ^Note that the [sqlcipher_sqlite3_wal_autocheckpoint()] interface and the
** [wal_autocheckpoint pragma] both invoke [sqlcipher_sqlite3_wal_hook()] and will
** overwrite any prior [sqlcipher_sqlite3_wal_hook()] settings.
*/
@@ -9316,20 +9596,277 @@ SQLITE_API int sqlcipher_sqlite3_vtab_nochange(sqlcipher_sqlite3_context*);
/*
** CAPI3REF: Determine The Collation For a Virtual Table Constraint
+** METHOD: sqlcipher_sqlite3_index_info
**
** This function may only be called from within a call to the [xBestIndex]
-** method of a [virtual table].
+** method of a [virtual table]. This function returns a pointer to a string
+** that is the name of the appropriate collation sequence to use for text
+** comparisons on the constraint identified by its arguments.
+**
+** The first argument must be the pointer to the [sqlcipher_sqlite3_index_info] object
+** that is the first parameter to the xBestIndex() method. The second argument
+** must be an index into the aConstraint[] array belonging to the
+** sqlcipher_sqlite3_index_info structure passed to xBestIndex.
+**
+** Important:
+** The first parameter must be the same pointer that is passed into the
+** xBestMethod() method. The first parameter may not be a pointer to a
+** different [sqlcipher_sqlite3_index_info] object, even an exact copy.
**
-** The first argument must be the sqlcipher_sqlite3_index_info object that is the
-** first parameter to the xBestIndex() method. The second argument must be
-** an index into the aConstraint[] array belonging to the sqlcipher_sqlite3_index_info
-** structure passed to xBestIndex. This function returns a pointer to a buffer
-** containing the name of the collation sequence for the corresponding
-** constraint.
+** The return value is computed as follows:
+**
+** <ol>
+** <li><p> If the constraint comes from a WHERE clause expression that contains
+** a [COLLATE operator], then the name of the collation specified by
+** that COLLATE operator is returned.
+** <li><p> If there is no COLLATE operator, but the column that is the subject
+** of the constraint specifies an alternative collating sequence via
+** a [COLLATE clause] on the column definition within the CREATE TABLE
+** statement that was passed into [sqlcipher_sqlite3_declare_vtab()], then the
+** name of that alternative collating sequence is returned.
+** <li><p> Otherwise, "BINARY" is returned.
+** </ol>
*/
SQLITE_API SQLITE_EXPERIMENTAL const char *sqlcipher_sqlite3_vtab_collation(sqlcipher_sqlite3_index_info*,int);
/*
+** CAPI3REF: Determine if a virtual table query is DISTINCT
+** METHOD: sqlcipher_sqlite3_index_info
+**
+** This API may only be used from within an [xBestIndex|xBestIndex method]
+** of a [virtual table] implementation. The result of calling this
+** interface from outside of xBestIndex() is undefined and probably harmful.
+**
+** ^The sqlcipher_sqlite3_vtab_distinct() interface returns an integer between 0 and
+** 3. The integer returned by sqlcipher_sqlite3_vtab_distinct()
+** gives the virtual table additional information about how the query
+** planner wants the output to be ordered. As long as the virtual table
+** can meet the ordering requirements of the query planner, it may set
+** the "orderByConsumed" flag.
+**
+** <ol><li value="0"><p>
+** ^If the sqlcipher_sqlite3_vtab_distinct() interface returns 0, that means
+** that the query planner needs the virtual table to return all rows in the
+** sort order defined by the "nOrderBy" and "aOrderBy" fields of the
+** [sqlcipher_sqlite3_index_info] object. This is the default expectation. If the
+** virtual table outputs all rows in sorted order, then it is always safe for
+** the xBestIndex method to set the "orderByConsumed" flag, regardless of
+** the return value from sqlcipher_sqlite3_vtab_distinct().
+** <li value="1"><p>
+** ^(If the sqlcipher_sqlite3_vtab_distinct() interface returns 1, that means
+** that the query planner does not need the rows to be returned in sorted order
+** as long as all rows with the same values in all columns identified by the
+** "aOrderBy" field are adjacent.)^ This mode is used when the query planner
+** is doing a GROUP BY.
+** <li value="2"><p>
+** ^(If the sqlcipher_sqlite3_vtab_distinct() interface returns 2, that means
+** that the query planner does not need the rows returned in any particular
+** order, as long as rows with the same values in all "aOrderBy" columns
+** are adjacent.)^ ^(Furthermore, only a single row for each particular
+** combination of values in the columns identified by the "aOrderBy" field
+** needs to be returned.)^ ^It is always ok for two or more rows with the same
+** values in all "aOrderBy" columns to be returned, as long as all such rows
+** are adjacent. ^The virtual table may, if it chooses, omit extra rows
+** that have the same value for all columns identified by "aOrderBy".
+** ^However omitting the extra rows is optional.
+** This mode is used for a DISTINCT query.
+** <li value="3"><p>
+** ^(If the sqlcipher_sqlite3_vtab_distinct() interface returns 3, that means
+** that the query planner needs only distinct rows but it does need the
+** rows to be sorted.)^ ^The virtual table implementation is free to omit
+** rows that are identical in all aOrderBy columns, if it wants to, but
+** it is not required to omit any rows. This mode is used for queries
+** that have both DISTINCT and ORDER BY clauses.
+** </ol>
+**
+** ^For the purposes of comparing virtual table output values to see if the
+** values are same value for sorting purposes, two NULL values are considered
+** to be the same. In other words, the comparison operator is "IS"
+** (or "IS NOT DISTINCT FROM") and not "==".
+**
+** If a virtual table implementation is unable to meet the requirements
+** specified above, then it must not set the "orderByConsumed" flag in the
+** [sqlcipher_sqlite3_index_info] object or an incorrect answer may result.
+**
+** ^A virtual table implementation is always free to return rows in any order
+** it wants, as long as the "orderByConsumed" flag is not set. ^When the
+** the "orderByConsumed" flag is unset, the query planner will add extra
+** [bytecode] to ensure that the final results returned by the SQL query are
+** ordered correctly. The use of the "orderByConsumed" flag and the
+** sqlcipher_sqlite3_vtab_distinct() interface is merely an optimization. ^Careful
+** use of the sqlcipher_sqlite3_vtab_distinct() interface and the "orderByConsumed"
+** flag might help queries against a virtual table to run faster. Being
+** overly aggressive and setting the "orderByConsumed" flag when it is not
+** valid to do so, on the other hand, might cause SQLite to return incorrect
+** results.
+*/
+SQLITE_API int sqlcipher_sqlite3_vtab_distinct(sqlcipher_sqlite3_index_info*);
+
+/*
+** CAPI3REF: Identify and handle IN constraints in xBestIndex
+**
+** This interface may only be used from within an
+** [xBestIndex|xBestIndex() method] of a [virtual table] implementation.
+** The result of invoking this interface from any other context is
+** undefined and probably harmful.
+**
+** ^(A constraint on a virtual table of the form
+** "[IN operator|column IN (...)]" is
+** communicated to the xBestIndex method as a
+** [SQLITE_INDEX_CONSTRAINT_EQ] constraint.)^ If xBestIndex wants to use
+** this constraint, it must set the corresponding
+** aConstraintUsage[].argvIndex to a postive integer. ^(Then, under
+** the usual mode of handling IN operators, SQLite generates [bytecode]
+** that invokes the [xFilter|xFilter() method] once for each value
+** on the right-hand side of the IN operator.)^ Thus the virtual table
+** only sees a single value from the right-hand side of the IN operator
+** at a time.
+**
+** In some cases, however, it would be advantageous for the virtual
+** table to see all values on the right-hand of the IN operator all at
+** once. The sqlcipher_sqlite3_vtab_in() interfaces facilitates this in two ways:
+**
+** <ol>
+** <li><p>
+** ^A call to sqlcipher_sqlite3_vtab_in(P,N,-1) will return true (non-zero)
+** if and only if the [sqlcipher_sqlite3_index_info|P->aConstraint][N] constraint
+** is an [IN operator] that can be processed all at once. ^In other words,
+** sqlcipher_sqlite3_vtab_in() with -1 in the third argument is a mechanism
+** by which the virtual table can ask SQLite if all-at-once processing
+** of the IN operator is even possible.
+**
+** <li><p>
+** ^A call to sqlcipher_sqlite3_vtab_in(P,N,F) with F==1 or F==0 indicates
+** to SQLite that the virtual table does or does not want to process
+** the IN operator all-at-once, respectively. ^Thus when the third
+** parameter (F) is non-negative, this interface is the mechanism by
+** which the virtual table tells SQLite how it wants to process the
+** IN operator.
+** </ol>
+**
+** ^The sqlcipher_sqlite3_vtab_in(P,N,F) interface can be invoked multiple times
+** within the same xBestIndex method call. ^For any given P,N pair,
+** the return value from sqlcipher_sqlite3_vtab_in(P,N,F) will always be the same
+** within the same xBestIndex call. ^If the interface returns true
+** (non-zero), that means that the constraint is an IN operator
+** that can be processed all-at-once. ^If the constraint is not an IN
+** operator or cannot be processed all-at-once, then the interface returns
+** false.
+**
+** ^(All-at-once processing of the IN operator is selected if both of the
+** following conditions are met:
+**
+** <ol>
+** <li><p> The P->aConstraintUsage[N].argvIndex value is set to a positive
+** integer. This is how the virtual table tells SQLite that it wants to
+** use the N-th constraint.
+**
+** <li><p> The last call to sqlcipher_sqlite3_vtab_in(P,N,F) for which F was
+** non-negative had F>=1.
+** </ol>)^
+**
+** ^If either or both of the conditions above are false, then SQLite uses
+** the traditional one-at-a-time processing strategy for the IN constraint.
+** ^If both conditions are true, then the argvIndex-th parameter to the
+** xFilter method will be an [sqlcipher_sqlite3_value] that appears to be NULL,
+** but which can be passed to [sqlcipher_sqlite3_vtab_in_first()] and
+** [sqlcipher_sqlite3_vtab_in_next()] to find all values on the right-hand side
+** of the IN constraint.
+*/
+SQLITE_API int sqlcipher_sqlite3_vtab_in(sqlcipher_sqlite3_index_info*, int iCons, int bHandle);
+
+/*
+** CAPI3REF: Find all elements on the right-hand side of an IN constraint.
+**
+** These interfaces are only useful from within the
+** [xFilter|xFilter() method] of a [virtual table] implementation.
+** The result of invoking these interfaces from any other context
+** is undefined and probably harmful.
+**
+** The X parameter in a call to sqlcipher_sqlite3_vtab_in_first(X,P) or
+** sqlcipher_sqlite3_vtab_in_next(X,P) must be one of the parameters to the
+** xFilter method which invokes these routines, and specifically
+** a parameter that was previously selected for all-at-once IN constraint
+** processing use the [sqlcipher_sqlite3_vtab_in()] interface in the
+** [xBestIndex|xBestIndex method]. ^(If the X parameter is not
+** an xFilter argument that was selected for all-at-once IN constraint
+** processing, then these routines return [SQLITE_MISUSE])^ or perhaps
+** exhibit some other undefined or harmful behavior.
+**
+** ^(Use these routines to access all values on the right-hand side
+** of the IN constraint using code like the following:
+**
+** <blockquote><pre>
+** &nbsp; for(rc=sqlcipher_sqlite3_vtab_in_first(pList, &pVal);
+** &nbsp; rc==SQLITE_OK && pVal
+** &nbsp; rc=sqlcipher_sqlite3_vtab_in_next(pList, &pVal)
+** &nbsp; ){
+** &nbsp; // do something with pVal
+** &nbsp; }
+** &nbsp; if( rc!=SQLITE_OK ){
+** &nbsp; // an error has occurred
+** &nbsp; }
+** </pre></blockquote>)^
+**
+** ^On success, the sqlcipher_sqlite3_vtab_in_first(X,P) and sqlcipher_sqlite3_vtab_in_next(X,P)
+** routines return SQLITE_OK and set *P to point to the first or next value
+** on the RHS of the IN constraint. ^If there are no more values on the
+** right hand side of the IN constraint, then *P is set to NULL and these
+** routines return [SQLITE_DONE]. ^The return value might be
+** some other value, such as SQLITE_NOMEM, in the event of a malfunction.
+**
+** The *ppOut values returned by these routines are only valid until the
+** next call to either of these routines or until the end of the xFilter
+** method from which these routines were called. If the virtual table
+** implementation needs to retain the *ppOut values for longer, it must make
+** copies. The *ppOut values are [protected sqlcipher_sqlite3_value|protected].
+*/
+SQLITE_API int sqlcipher_sqlite3_vtab_in_first(sqlcipher_sqlite3_value *pVal, sqlcipher_sqlite3_value **ppOut);
+SQLITE_API int sqlcipher_sqlite3_vtab_in_next(sqlcipher_sqlite3_value *pVal, sqlcipher_sqlite3_value **ppOut);
+
+/*
+** CAPI3REF: Constraint values in xBestIndex()
+** METHOD: sqlcipher_sqlite3_index_info
+**
+** This API may only be used from within the [xBestIndex|xBestIndex method]
+** of a [virtual table] implementation. The result of calling this interface
+** from outside of an xBestIndex method are undefined and probably harmful.
+**
+** ^When the sqlcipher_sqlite3_vtab_rhs_value(P,J,V) interface is invoked from within
+** the [xBestIndex] method of a [virtual table] implementation, with P being
+** a copy of the [sqlcipher_sqlite3_index_info] object pointer passed into xBestIndex and
+** J being a 0-based index into P->aConstraint[], then this routine
+** attempts to set *V to the value of the right-hand operand of
+** that constraint if the right-hand operand is known. ^If the
+** right-hand operand is not known, then *V is set to a NULL pointer.
+** ^The sqlcipher_sqlite3_vtab_rhs_value(P,J,V) interface returns SQLITE_OK if
+** and only if *V is set to a value. ^The sqlcipher_sqlite3_vtab_rhs_value(P,J,V)
+** inteface returns SQLITE_NOTFOUND if the right-hand side of the J-th
+** constraint is not available. ^The sqlcipher_sqlite3_vtab_rhs_value() interface
+** can return an result code other than SQLITE_OK or SQLITE_NOTFOUND if
+** something goes wrong.
+**
+** The sqlcipher_sqlite3_vtab_rhs_value() interface is usually only successful if
+** the right-hand operand of a constraint is a literal value in the original
+** SQL statement. If the right-hand operand is an expression or a reference
+** to some other column or a [host parameter], then sqlcipher_sqlite3_vtab_rhs_value()
+** will probably return [SQLITE_NOTFOUND].
+**
+** ^(Some constraints, such as [SQLITE_INDEX_CONSTRAINT_ISNULL] and
+** [SQLITE_INDEX_CONSTRAINT_ISNOTNULL], have no right-hand operand. For such
+** constraints, sqlcipher_sqlite3_vtab_rhs_value() always returns SQLITE_NOTFOUND.)^
+**
+** ^The [sqlcipher_sqlite3_value] object returned in *V is a protected sqlcipher_sqlite3_value
+** and remains valid for the duration of the xBestIndex method call.
+** ^When xBestIndex returns, the sqlcipher_sqlite3_value object returned by
+** sqlcipher_sqlite3_vtab_rhs_value() is automatically deallocated.
+**
+** The "_rhs_" in the name of this routine is an abbreviation for
+** "Right-Hand Side".
+*/
+SQLITE_API int sqlcipher_sqlite3_vtab_rhs_value(sqlcipher_sqlite3_index_info*, int, sqlcipher_sqlite3_value **ppVal);
+
+/*
** CAPI3REF: Conflict resolution modes
** KEYWORDS: {conflict resolution mode}
**
@@ -9564,6 +10101,15 @@ SQLITE_API int sqlcipher_sqlite3_db_cacheflush(sqlcipher_sqlite3*);
** triggers; or 2 for changes resulting from triggers called by top-level
** triggers; and so forth.
**
+** When the [sqlcipher_sqlite3_blob_write()] API is used to update a blob column,
+** the pre-update hook is invoked with SQLITE_DELETE. This is because the
+** in this case the new values are not available. In this case, when a
+** callback made with op==SQLITE_DELETE is actuall a write using the
+** sqlcipher_sqlite3_blob_write() API, the [sqlcipher_sqlite3_preupdate_blobwrite()] returns
+** the index of the column being written. In other cases, where the
+** pre-update hook is being invoked for some other reason, including a
+** regular DELETE, sqlcipher_sqlite3_preupdate_blobwrite() returns -1.
+**
** See also: [sqlcipher_sqlite3_update_hook()]
*/
#if defined(SQLITE_ENABLE_PREUPDATE_HOOK)
@@ -9584,6 +10130,7 @@ SQLITE_API int sqlcipher_sqlite3_preupdate_old(sqlcipher_sqlite3 *, int, sqlciph
SQLITE_API int sqlcipher_sqlite3_preupdate_count(sqlcipher_sqlite3 *);
SQLITE_API int sqlcipher_sqlite3_preupdate_depth(sqlcipher_sqlite3 *);
SQLITE_API int sqlcipher_sqlite3_preupdate_new(sqlcipher_sqlite3 *, int, sqlcipher_sqlite3_value **);
+SQLITE_API int sqlcipher_sqlite3_preupdate_blobwrite(sqlcipher_sqlite3 *);
#endif
/*
@@ -9822,8 +10369,8 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlcipher_sqlite3_snapshot_recover(sqlcipher_
** SQLITE_SERIALIZE_NOCOPY bit is omitted from argument F if a memory
** allocation error occurs.
**
-** This interface is only available if SQLite is compiled with the
-** [SQLITE_ENABLE_DESERIALIZE] option.
+** This interface is omitted if SQLite is compiled with the
+** [SQLITE_OMIT_DESERIALIZE] option.
*/
SQLITE_API unsigned char *sqlcipher_sqlite3_serialize(
sqlcipher_sqlite3 *db, /* The database connection */
@@ -9870,12 +10417,16 @@ SQLITE_API unsigned char *sqlcipher_sqlite3_serialize(
** database is currently in a read transaction or is involved in a backup
** operation.
**
+** It is not possible to deserialized into the TEMP database. If the
+** S argument to sqlcipher_sqlite3_deserialize(D,S,P,N,M,F) is "temp" then the
+** function returns SQLITE_ERROR.
+**
** If sqlcipher_sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the
** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then
** [sqlcipher_sqlite3_free()] is invoked on argument P prior to returning.
**
-** This interface is only available if SQLite is compiled with the
-** [SQLITE_ENABLE_DESERIALIZE] option.
+** This interface is omitted if SQLite is compiled with the
+** [SQLITE_OMIT_DESERIALIZE] option.
*/
SQLITE_API int sqlcipher_sqlite3_deserialize(
sqlcipher_sqlite3 *db, /* The database connection */
@@ -10124,6 +10675,38 @@ SQLITE_API int sqlcipher_sqlite3session_create(
*/
SQLITE_API void sqlcipher_sqlite3session_delete(sqlcipher_sqlite3_session *pSession);
+/*
+** CAPIREF: Conigure a Session Object
+** METHOD: sqlcipher_sqlite3_session
+**
+** This method is used to configure a session object after it has been
+** created. At present the only valid value for the second parameter is
+** [SQLITE_SESSION_OBJCONFIG_SIZE].
+**
+** Arguments for sqlcipher_sqlite3session_object_config()
+**
+** The following values may passed as the the 4th parameter to
+** sqlcipher_sqlite3session_object_config().
+**
+** <dt>SQLITE_SESSION_OBJCONFIG_SIZE <dd>
+** This option is used to set, clear or query the flag that enables
+** the [sqlcipher_sqlite3session_changeset_size()] API. Because it imposes some
+** computational overhead, this API is disabled by default. Argument
+** pArg must point to a value of type (int). If the value is initially
+** 0, then the sqlcipher_sqlite3session_changeset_size() API is disabled. If it
+** is greater than 0, then the same API is enabled. Or, if the initial
+** value is less than zero, no change is made. In all cases the (int)
+** variable is set to 1 if the sqlcipher_sqlite3session_changeset_size() API is
+** enabled following the current call, or 0 otherwise.
+**
+** It is an error (SQLITE_MISUSE) to attempt to modify this setting after
+** the first table has been attached to the session object.
+*/
+SQLITE_API int sqlcipher_sqlite3session_object_config(sqlcipher_sqlite3_session*, int op, void *pArg);
+
+/*
+*/
+#define SQLITE_SESSION_OBJCONFIG_SIZE 1
/*
** CAPI3REF: Enable Or Disable A Session Object
@@ -10369,6 +10952,22 @@ SQLITE_API int sqlcipher_sqlite3session_changeset(
);
/*
+** CAPI3REF: Return An Upper-limit For The Size Of The Changeset
+** METHOD: sqlcipher_sqlite3_session
+**
+** By default, this function always returns 0. For it to return
+** a useful result, the sqlcipher_sqlite3_session object must have been configured
+** to enable this API using sqlcipher_sqlite3session_object_config() with the
+** SQLITE_SESSION_OBJCONFIG_SIZE verb.
+**
+** When enabled, this function returns an upper limit, in bytes, for the size
+** of the changeset that might be produced if sqlcipher_sqlite3session_changeset() were
+** called. The final changeset size might be equal to or smaller than the
+** size in bytes returned by this function.
+*/
+SQLITE_API sqlcipher_sqlite3_int64 sqlcipher_sqlite3session_changeset_size(sqlcipher_sqlite3_session *pSession);
+
+/*
** CAPI3REF: Load The Difference Between Tables Into A Session
** METHOD: sqlcipher_sqlite3_session
**
@@ -10486,6 +11085,14 @@ SQLITE_API int sqlcipher_sqlite3session_patchset(
SQLITE_API int sqlcipher_sqlite3session_isempty(sqlcipher_sqlite3_session *pSession);
/*
+** CAPI3REF: Query for the amount of heap memory used by a session object.
+**
+** This API returns the total amount of heap memory in bytes currently
+** used by the session object passed as the only argument.
+*/
+SQLITE_API sqlcipher_sqlite3_int64 sqlcipher_sqlite3session_memory_used(sqlcipher_sqlite3_session *pSession);
+
+/*
** CAPI3REF: Create An Iterator To Traverse A Changeset
** CONSTRUCTOR: sqlcipher_sqlite3_changeset_iter
**
@@ -10587,18 +11194,23 @@ SQLITE_API int sqlcipher_sqlite3changeset_next(sqlcipher_sqlite3_changeset_iter
** call to [sqlcipher_sqlite3changeset_next()] must have returned [SQLITE_ROW]. If this
** is not the case, this function returns [SQLITE_MISUSE].
**
-** If argument pzTab is not NULL, then *pzTab is set to point to a
-** nul-terminated utf-8 encoded string containing the name of the table
-** affected by the current change. The buffer remains valid until either
-** sqlcipher_sqlite3changeset_next() is called on the iterator or until the
-** conflict-handler function returns. If pnCol is not NULL, then *pnCol is
-** set to the number of columns in the table affected by the change. If
-** pbIndirect is not NULL, then *pbIndirect is set to true (1) if the change
+** Arguments pOp, pnCol and pzTab may not be NULL. Upon return, three
+** outputs are set through these pointers:
+**
+** *pOp is set to one of [SQLITE_INSERT], [SQLITE_DELETE] or [SQLITE_UPDATE],
+** depending on the type of change that the iterator currently points to;
+**
+** *pnCol is set to the number of columns in the table affected by the change; and
+**
+** *pzTab is set to point to a nul-terminated utf-8 encoded string containing
+** the name of the table affected by the current change. The buffer remains
+** valid until either sqlcipher_sqlite3changeset_next() is called on the iterator
+** or until the conflict-handler function returns.
+**
+** If pbIndirect is not NULL, then *pbIndirect is set to true (1) if the change
** is an indirect change, or false (0) otherwise. See the documentation for
** [sqlcipher_sqlite3session_indirect()] for a description of direct and indirect
-** changes. Finally, if pOp is not NULL, then *pOp is set to one of
-** [SQLITE_INSERT], [SQLITE_DELETE] or [SQLITE_UPDATE], depending on the
-** type of change that the iterator currently points to.
+** changes.
**
** If no error occurs, SQLITE_OK is returned. If an error does occur, an
** SQLite error code is returned. The values of the output variables may not
diff --git a/Plugins/DbSqliteCipher/translations/DbSqliteCipher.ts b/Plugins/DbSqliteCipher/translations/DbSqliteCipher.ts
new file mode 100644
index 0000000..876a5b8
--- /dev/null
+++ b/Plugins/DbSqliteCipher/translations/DbSqliteCipher.ts
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1">
+ <context>
+ <name>DbSqliteCipher</name>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="30"/>
+ <source>Password (key)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="31"/>
+ <source>Leave empty to create or connect to decrypted database.</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="32"/>
+ <source>Encryption password</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="37"/>
+ <source>Cipher configuration (optional)</source>
+ <translation type="unfinished"/>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="38"/>
+ <source>PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</source>
+ <translation type="unfinished"/>
+ </message>
+ </context>
+</TS>
diff --git a/Plugins/DbSqliteCipher/translations/DbSqliteCipher_af_ZA.ts b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_af_ZA.ts
new file mode 100644
index 0000000..bf0965e
--- /dev/null
+++ b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_af_ZA.ts
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="af" sourcelanguage="en">
+ <context>
+ <name>DbSqliteCipher</name>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="30"/>
+ <source>Password (key)</source>
+ <translation type="unfinished">Password (key)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="31"/>
+ <source>Leave empty to create or connect to decrypted database.</source>
+ <translation type="unfinished">Leave empty to create or connect to decrypted database.</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="32"/>
+ <source>Encryption password</source>
+ <translation type="unfinished">Encryption password</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="37"/>
+ <source>Cipher configuration (optional)</source>
+ <translation type="unfinished">Cipher configuration (optional)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="38"/>
+ <source>PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</source>
+ <translation type="unfinished">PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</translation>
+ </message>
+ </context>
+</TS>
diff --git a/Plugins/DbSqliteCipher/translations/DbSqliteCipher_ar_SA.ts b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_ar_SA.ts
new file mode 100644
index 0000000..9bd8d76
--- /dev/null
+++ b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_ar_SA.ts
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="ar" sourcelanguage="en">
+ <context>
+ <name>DbSqliteCipher</name>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="30"/>
+ <source>Password (key)</source>
+ <translation type="unfinished">Password (key)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="31"/>
+ <source>Leave empty to create or connect to decrypted database.</source>
+ <translation type="unfinished">Leave empty to create or connect to decrypted database.</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="32"/>
+ <source>Encryption password</source>
+ <translation type="unfinished">Encryption password</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="37"/>
+ <source>Cipher configuration (optional)</source>
+ <translation type="unfinished">Cipher configuration (optional)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="38"/>
+ <source>PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</source>
+ <translation type="unfinished">PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</translation>
+ </message>
+ </context>
+</TS>
diff --git a/Plugins/DbSqliteCipher/translations/DbSqliteCipher_ca_ES.ts b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_ca_ES.ts
new file mode 100644
index 0000000..57b2c49
--- /dev/null
+++ b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_ca_ES.ts
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="ca" sourcelanguage="en">
+ <context>
+ <name>DbSqliteCipher</name>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="30"/>
+ <source>Password (key)</source>
+ <translation type="unfinished">Password (key)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="31"/>
+ <source>Leave empty to create or connect to decrypted database.</source>
+ <translation type="unfinished">Leave empty to create or connect to decrypted database.</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="32"/>
+ <source>Encryption password</source>
+ <translation type="unfinished">Encryption password</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="37"/>
+ <source>Cipher configuration (optional)</source>
+ <translation type="unfinished">Cipher configuration (optional)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="38"/>
+ <source>PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</source>
+ <translation type="unfinished">PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</translation>
+ </message>
+ </context>
+</TS>
diff --git a/Plugins/DbSqliteCipher/translations/DbSqliteCipher_cs_CZ.ts b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_cs_CZ.ts
new file mode 100644
index 0000000..528339c
--- /dev/null
+++ b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_cs_CZ.ts
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="cs" sourcelanguage="en">
+ <context>
+ <name>DbSqliteCipher</name>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="30"/>
+ <source>Password (key)</source>
+ <translation type="unfinished">Password (key)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="31"/>
+ <source>Leave empty to create or connect to decrypted database.</source>
+ <translation type="unfinished">Leave empty to create or connect to decrypted database.</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="32"/>
+ <source>Encryption password</source>
+ <translation type="unfinished">Encryption password</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="37"/>
+ <source>Cipher configuration (optional)</source>
+ <translation type="unfinished">Cipher configuration (optional)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="38"/>
+ <source>PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</source>
+ <translation type="unfinished">PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</translation>
+ </message>
+ </context>
+</TS>
diff --git a/Plugins/DbSqliteCipher/translations/DbSqliteCipher_da_DK.ts b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_da_DK.ts
new file mode 100644
index 0000000..18b81f3
--- /dev/null
+++ b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_da_DK.ts
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="da" sourcelanguage="en">
+ <context>
+ <name>DbSqliteCipher</name>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="30"/>
+ <source>Password (key)</source>
+ <translation type="unfinished">Password (key)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="31"/>
+ <source>Leave empty to create or connect to decrypted database.</source>
+ <translation type="unfinished">Leave empty to create or connect to decrypted database.</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="32"/>
+ <source>Encryption password</source>
+ <translation type="unfinished">Encryption password</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="37"/>
+ <source>Cipher configuration (optional)</source>
+ <translation type="unfinished">Cipher configuration (optional)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="38"/>
+ <source>PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</source>
+ <translation type="unfinished">PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</translation>
+ </message>
+ </context>
+</TS>
diff --git a/Plugins/DbSqliteCipher/translations/DbSqliteCipher_de_DE.ts b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_de_DE.ts
new file mode 100644
index 0000000..4a99fad
--- /dev/null
+++ b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_de_DE.ts
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="de" sourcelanguage="en">
+ <context>
+ <name>DbSqliteCipher</name>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="30"/>
+ <source>Password (key)</source>
+ <translation>Passwort (Schlüssel)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="31"/>
+ <source>Leave empty to create or connect to decrypted database.</source>
+ <translation>Leer lassen, um die entschlüsselte Datenbank zu erstellen oder sich damit zu verbinden.</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="32"/>
+ <source>Encryption password</source>
+ <translation>Verschlüsselungspasswort</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="37"/>
+ <source>Cipher configuration (optional)</source>
+ <translation>Cipher-Konfiguration (optional)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="38"/>
+ <source>PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</source>
+ <translation>PRAGMA Anweisungen zur Anpassung der SQLCipher Konfiguration, wie z. B. KDF-Iterationen, Legacy-Modus, etc.
+Sie werden bei jedem Öffnen der Datenbank ausgeführt.
+Siehe Dokumentation für SQLCipher für Details.</translation>
+ </message>
+ </context>
+</TS>
diff --git a/Plugins/DbSqliteCipher/translations/DbSqliteCipher_el_GR.ts b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_el_GR.ts
new file mode 100644
index 0000000..be2857b
--- /dev/null
+++ b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_el_GR.ts
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="el" sourcelanguage="en">
+ <context>
+ <name>DbSqliteCipher</name>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="30"/>
+ <source>Password (key)</source>
+ <translation type="unfinished">Password (key)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="31"/>
+ <source>Leave empty to create or connect to decrypted database.</source>
+ <translation type="unfinished">Leave empty to create or connect to decrypted database.</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="32"/>
+ <source>Encryption password</source>
+ <translation type="unfinished">Encryption password</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="37"/>
+ <source>Cipher configuration (optional)</source>
+ <translation type="unfinished">Cipher configuration (optional)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="38"/>
+ <source>PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</source>
+ <translation type="unfinished">PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</translation>
+ </message>
+ </context>
+</TS>
diff --git a/Plugins/DbSqliteCipher/translations/DbSqliteCipher_en_US.ts b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_en_US.ts
new file mode 100644
index 0000000..a39673b
--- /dev/null
+++ b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_en_US.ts
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="en" sourcelanguage="en">
+ <context>
+ <name>DbSqliteCipher</name>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="30"/>
+ <source>Password (key)</source>
+ <translation type="unfinished">Password (key)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="31"/>
+ <source>Leave empty to create or connect to decrypted database.</source>
+ <translation type="unfinished">Leave empty to create or connect to decrypted database.</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="32"/>
+ <source>Encryption password</source>
+ <translation type="unfinished">Encryption password</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="37"/>
+ <source>Cipher configuration (optional)</source>
+ <translation type="unfinished">Cipher configuration (optional)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="38"/>
+ <source>PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</source>
+ <translation type="unfinished">PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</translation>
+ </message>
+ </context>
+</TS>
diff --git a/Plugins/DbSqliteCipher/translations/DbSqliteCipher_es_ES.ts b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_es_ES.ts
new file mode 100644
index 0000000..5ba7ed5
--- /dev/null
+++ b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_es_ES.ts
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="es-ES" sourcelanguage="en">
+ <context>
+ <name>DbSqliteCipher</name>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="30"/>
+ <source>Password (key)</source>
+ <translation>Contraseña (clave)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="31"/>
+ <source>Leave empty to create or connect to decrypted database.</source>
+ <translation>Dejar en blanco para crear o conectarse a una base de datos desencriptada.</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="32"/>
+ <source>Encryption password</source>
+ <translation>Contraseña de encriptado</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="37"/>
+ <source>Cipher configuration (optional)</source>
+ <translation type="unfinished">Cipher configuration (optional)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="38"/>
+ <source>PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</source>
+ <translation type="unfinished">PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</translation>
+ </message>
+ </context>
+</TS>
diff --git a/Plugins/DbSqliteCipher/translations/DbSqliteCipher_fa_IR.ts b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_fa_IR.ts
new file mode 100644
index 0000000..cdb29fb
--- /dev/null
+++ b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_fa_IR.ts
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="fa" sourcelanguage="en">
+ <context>
+ <name>DbSqliteCipher</name>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="30"/>
+ <source>Password (key)</source>
+ <translation type="unfinished">Password (key)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="31"/>
+ <source>Leave empty to create or connect to decrypted database.</source>
+ <translation type="unfinished">Leave empty to create or connect to decrypted database.</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="32"/>
+ <source>Encryption password</source>
+ <translation type="unfinished">Encryption password</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="37"/>
+ <source>Cipher configuration (optional)</source>
+ <translation type="unfinished">Cipher configuration (optional)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="38"/>
+ <source>PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</source>
+ <translation type="unfinished">PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</translation>
+ </message>
+ </context>
+</TS>
diff --git a/Plugins/DbSqliteCipher/translations/DbSqliteCipher_fi_FI.ts b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_fi_FI.ts
new file mode 100644
index 0000000..a46be5d
--- /dev/null
+++ b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_fi_FI.ts
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="fi" sourcelanguage="en">
+ <context>
+ <name>DbSqliteCipher</name>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="30"/>
+ <source>Password (key)</source>
+ <translation type="unfinished">Password (key)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="31"/>
+ <source>Leave empty to create or connect to decrypted database.</source>
+ <translation type="unfinished">Leave empty to create or connect to decrypted database.</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="32"/>
+ <source>Encryption password</source>
+ <translation type="unfinished">Encryption password</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="37"/>
+ <source>Cipher configuration (optional)</source>
+ <translation type="unfinished">Cipher configuration (optional)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="38"/>
+ <source>PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</source>
+ <translation type="unfinished">PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</translation>
+ </message>
+ </context>
+</TS>
diff --git a/Plugins/DbSqliteCipher/translations/DbSqliteCipher_fr_FR.ts b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_fr_FR.ts
new file mode 100644
index 0000000..a424d07
--- /dev/null
+++ b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_fr_FR.ts
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="fr" sourcelanguage="en">
+ <context>
+ <name>DbSqliteCipher</name>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="30"/>
+ <source>Password (key)</source>
+ <translation>Mot de passe (clé)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="31"/>
+ <source>Leave empty to create or connect to decrypted database.</source>
+ <translation>Laisser vide pour créer ou se connecter à la base de données déchiffrée.</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="32"/>
+ <source>Encryption password</source>
+ <translation>Mot de passe de chiffrement</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="37"/>
+ <source>Cipher configuration (optional)</source>
+ <translation>Configuration du chiffrement (optionnel)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="38"/>
+ <source>PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</source>
+ <translation type="unfinished">PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</translation>
+ </message>
+ </context>
+</TS>
diff --git a/Plugins/DbSqliteCipher/translations/DbSqliteCipher_he_IL.ts b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_he_IL.ts
new file mode 100644
index 0000000..403982f
--- /dev/null
+++ b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_he_IL.ts
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="he" sourcelanguage="en">
+ <context>
+ <name>DbSqliteCipher</name>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="30"/>
+ <source>Password (key)</source>
+ <translation>ססמה (מפתח)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="31"/>
+ <source>Leave empty to create or connect to decrypted database.</source>
+ <translation>להשאיר ריק ליצירת או התחברות למסד נתונים לא מוצפן.</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="32"/>
+ <source>Encryption password</source>
+ <translation>ססמה מוצפנת</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="37"/>
+ <source>Cipher configuration (optional)</source>
+ <translation>תצורת צופן (חלופי)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="38"/>
+ <source>PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</source>
+ <translation>הצהרות PRAGMA להתאמה אישית של תצורת SQLCipher, כגון חִזְרוּר KDF, מצב מורשת ועוד.
+יופעלו עם כל פתיחה של מסד הנתונים.
+לפרטים, נא עיין בתיעוד SQLCipher.</translation>
+ </message>
+ </context>
+</TS>
diff --git a/Plugins/DbSqliteCipher/translations/DbSqliteCipher_hu_HU.ts b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_hu_HU.ts
new file mode 100644
index 0000000..1ec5e9d
--- /dev/null
+++ b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_hu_HU.ts
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="hu" sourcelanguage="en">
+ <context>
+ <name>DbSqliteCipher</name>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="30"/>
+ <source>Password (key)</source>
+ <translation>Jelszó (kulcs)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="31"/>
+ <source>Leave empty to create or connect to decrypted database.</source>
+ <translation>Titkosítás nélküli adatbázishoz csatlakozáshoz vagy létrehozásához hagyja üresen.</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="32"/>
+ <source>Encryption password</source>
+ <translation>Titkosító jelszó</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="37"/>
+ <source>Cipher configuration (optional)</source>
+ <translation>Titkosítás konfiguráció (opcionális)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="38"/>
+ <source>PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</source>
+ <translation>PRAGMA kifejezések az SQLCipher konfigurálásához, mint például KDF iterációk, legacy mód stb.
+Az adatbázis minden megnyitásakor végre lesznek hajtva.
+Lásd az SQLCipher dokumentációját a részletekhez.</translation>
+ </message>
+ </context>
+</TS>
diff --git a/Plugins/DbSqliteCipher/translations/DbSqliteCipher_it_IT.ts b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_it_IT.ts
new file mode 100644
index 0000000..cb06d40
--- /dev/null
+++ b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_it_IT.ts
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="it" sourcelanguage="en">
+ <context>
+ <name>DbSqliteCipher</name>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="30"/>
+ <source>Password (key)</source>
+ <translation>Password (chiave)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="31"/>
+ <source>Leave empty to create or connect to decrypted database.</source>
+ <translation>Lasciare vuoto per creare o connettersi al database decriptato.</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="32"/>
+ <source>Encryption password</source>
+ <translation>Password di crittografia</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="37"/>
+ <source>Cipher configuration (optional)</source>
+ <translation>Configurazione di Cifratura (opzionale)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="38"/>
+ <source>PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</source>
+ <translation>Dichiarazioni PRAGMA per personalizzare la configurazione di SQLCipher, come iterazioni KDF, modalità legacy, ecc.
+Esse verranno eseguite dopo ogni apertura del database.
+Vedi la documentazione per SQLCipher per dettagli.</translation>
+ </message>
+ </context>
+</TS>
diff --git a/Plugins/DbSqliteCipher/translations/DbSqliteCipher_ja_JP.ts b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_ja_JP.ts
new file mode 100644
index 0000000..f98f0a8
--- /dev/null
+++ b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_ja_JP.ts
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="ja" sourcelanguage="en">
+ <context>
+ <name>DbSqliteCipher</name>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="30"/>
+ <source>Password (key)</source>
+ <translation type="unfinished">Password (key)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="31"/>
+ <source>Leave empty to create or connect to decrypted database.</source>
+ <translation type="unfinished">Leave empty to create or connect to decrypted database.</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="32"/>
+ <source>Encryption password</source>
+ <translation type="unfinished">Encryption password</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="37"/>
+ <source>Cipher configuration (optional)</source>
+ <translation type="unfinished">Cipher configuration (optional)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="38"/>
+ <source>PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</source>
+ <translation type="unfinished">PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</translation>
+ </message>
+ </context>
+</TS>
diff --git a/Plugins/DbSqliteCipher/translations/DbSqliteCipher_kaa.ts b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_kaa.ts
new file mode 100644
index 0000000..7f2d7fb
--- /dev/null
+++ b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_kaa.ts
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="kaa" sourcelanguage="en">
+ <context>
+ <name>DbSqliteCipher</name>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="30"/>
+ <source>Password (key)</source>
+ <translation type="unfinished">Password (key)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="31"/>
+ <source>Leave empty to create or connect to decrypted database.</source>
+ <translation type="unfinished">Leave empty to create or connect to decrypted database.</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="32"/>
+ <source>Encryption password</source>
+ <translation type="unfinished">Encryption password</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="37"/>
+ <source>Cipher configuration (optional)</source>
+ <translation type="unfinished">Cipher configuration (optional)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="38"/>
+ <source>PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</source>
+ <translation type="unfinished">PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</translation>
+ </message>
+ </context>
+</TS>
diff --git a/Plugins/DbSqliteCipher/translations/DbSqliteCipher_ko_KR.ts b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_ko_KR.ts
new file mode 100644
index 0000000..8ea0420
--- /dev/null
+++ b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_ko_KR.ts
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="ko" sourcelanguage="en">
+ <context>
+ <name>DbSqliteCipher</name>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="30"/>
+ <source>Password (key)</source>
+ <translation type="unfinished">Password (key)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="31"/>
+ <source>Leave empty to create or connect to decrypted database.</source>
+ <translation type="unfinished">Leave empty to create or connect to decrypted database.</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="32"/>
+ <source>Encryption password</source>
+ <translation type="unfinished">Encryption password</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="37"/>
+ <source>Cipher configuration (optional)</source>
+ <translation type="unfinished">Cipher configuration (optional)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="38"/>
+ <source>PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</source>
+ <translation type="unfinished">PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</translation>
+ </message>
+ </context>
+</TS>
diff --git a/Plugins/DbSqliteCipher/translations/DbSqliteCipher_nl_NL.ts b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_nl_NL.ts
new file mode 100644
index 0000000..a4084e8
--- /dev/null
+++ b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_nl_NL.ts
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="nl" sourcelanguage="en">
+ <context>
+ <name>DbSqliteCipher</name>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="30"/>
+ <source>Password (key)</source>
+ <translation type="unfinished">Password (key)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="31"/>
+ <source>Leave empty to create or connect to decrypted database.</source>
+ <translation type="unfinished">Leave empty to create or connect to decrypted database.</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="32"/>
+ <source>Encryption password</source>
+ <translation type="unfinished">Encryption password</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="37"/>
+ <source>Cipher configuration (optional)</source>
+ <translation type="unfinished">Cipher configuration (optional)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="38"/>
+ <source>PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</source>
+ <translation type="unfinished">PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</translation>
+ </message>
+ </context>
+</TS>
diff --git a/Plugins/DbSqliteCipher/translations/DbSqliteCipher_no_NO.ts b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_no_NO.ts
new file mode 100644
index 0000000..c84c172
--- /dev/null
+++ b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_no_NO.ts
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="no" sourcelanguage="en">
+ <context>
+ <name>DbSqliteCipher</name>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="30"/>
+ <source>Password (key)</source>
+ <translation type="unfinished">Password (key)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="31"/>
+ <source>Leave empty to create or connect to decrypted database.</source>
+ <translation type="unfinished">Leave empty to create or connect to decrypted database.</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="32"/>
+ <source>Encryption password</source>
+ <translation type="unfinished">Encryption password</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="37"/>
+ <source>Cipher configuration (optional)</source>
+ <translation type="unfinished">Cipher configuration (optional)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="38"/>
+ <source>PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</source>
+ <translation type="unfinished">PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</translation>
+ </message>
+ </context>
+</TS>
diff --git a/Plugins/DbSqliteCipher/translations/DbSqliteCipher_pl_PL.ts b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_pl_PL.ts
new file mode 100644
index 0000000..1db1a17
--- /dev/null
+++ b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_pl_PL.ts
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="pl" sourcelanguage="en">
+ <context>
+ <name>DbSqliteCipher</name>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="30"/>
+ <source>Password (key)</source>
+ <translation>Hasło (klucz)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="31"/>
+ <source>Leave empty to create or connect to decrypted database.</source>
+ <translation>Pozostaw puste, aby stworzyć lub połączyć się z niezaszyfrowaną bazą.</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="32"/>
+ <source>Encryption password</source>
+ <translation>Hasło szyfrowania</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="37"/>
+ <source>Cipher configuration (optional)</source>
+ <translation>Konfiguracja szyfrowania (opcjonalna)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="38"/>
+ <source>PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</source>
+ <translation>Instrukcje PRAGMA dostosowujące konfigurację SQLCipher, takie jak liczba iteracji KDF, starszy tryb, itp.
+Zostaną one wykonane po każdym otwarciu bazy danych.
+Zobacz dokumentację dla SQLCipher, aby poznać więcej szczegółów.</translation>
+ </message>
+ </context>
+</TS>
diff --git a/Plugins/DbSqliteCipher/translations/DbSqliteCipher_pt_BR.ts b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_pt_BR.ts
new file mode 100644
index 0000000..2601958
--- /dev/null
+++ b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_pt_BR.ts
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="pt-BR" sourcelanguage="en">
+ <context>
+ <name>DbSqliteCipher</name>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="30"/>
+ <source>Password (key)</source>
+ <translation>Senha (chave)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="31"/>
+ <source>Leave empty to create or connect to decrypted database.</source>
+ <translation>Deixe em branco para criar ou conectar ao banco de dados descriptografado.</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="32"/>
+ <source>Encryption password</source>
+ <translation>Senha criptografada</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="37"/>
+ <source>Cipher configuration (optional)</source>
+ <translation>Configuração de cifra (opcional)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="38"/>
+ <source>PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</source>
+ <translation>Declarações PRAGMA para personalizar a configuração SQLCipher, como iterações KDF, modo legado, etc.
+Eles serão executados após cada abertura do banco de dados.
+Consulte a documentação de SQLCipher para obter detalhes.</translation>
+ </message>
+ </context>
+</TS>
diff --git a/Plugins/DbSqliteCipher/translations/DbSqliteCipher_pt_PT.ts b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_pt_PT.ts
new file mode 100644
index 0000000..88372ad
--- /dev/null
+++ b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_pt_PT.ts
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="pt-PT" sourcelanguage="en">
+ <context>
+ <name>DbSqliteCipher</name>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="30"/>
+ <source>Password (key)</source>
+ <translation type="unfinished">Password (key)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="31"/>
+ <source>Leave empty to create or connect to decrypted database.</source>
+ <translation type="unfinished">Leave empty to create or connect to decrypted database.</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="32"/>
+ <source>Encryption password</source>
+ <translation type="unfinished">Encryption password</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="37"/>
+ <source>Cipher configuration (optional)</source>
+ <translation type="unfinished">Cipher configuration (optional)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="38"/>
+ <source>PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</source>
+ <translation type="unfinished">PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</translation>
+ </message>
+ </context>
+</TS>
diff --git a/Plugins/DbSqliteCipher/translations/DbSqliteCipher_ro_RO.ts b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_ro_RO.ts
new file mode 100644
index 0000000..f89a267
--- /dev/null
+++ b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_ro_RO.ts
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="ro" sourcelanguage="en">
+ <context>
+ <name>DbSqliteCipher</name>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="30"/>
+ <source>Password (key)</source>
+ <translation type="unfinished">Password (key)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="31"/>
+ <source>Leave empty to create or connect to decrypted database.</source>
+ <translation type="unfinished">Leave empty to create or connect to decrypted database.</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="32"/>
+ <source>Encryption password</source>
+ <translation type="unfinished">Encryption password</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="37"/>
+ <source>Cipher configuration (optional)</source>
+ <translation type="unfinished">Cipher configuration (optional)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="38"/>
+ <source>PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</source>
+ <translation type="unfinished">PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</translation>
+ </message>
+ </context>
+</TS>
diff --git a/Plugins/DbSqliteCipher/translations/DbSqliteCipher_ru_RU.ts b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_ru_RU.ts
new file mode 100644
index 0000000..ce4991c
--- /dev/null
+++ b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_ru_RU.ts
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="ru" sourcelanguage="en">
+ <context>
+ <name>DbSqliteCipher</name>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="30"/>
+ <source>Password (key)</source>
+ <translation>Пароль (ключ)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="31"/>
+ <source>Leave empty to create or connect to decrypted database.</source>
+ <translation>Оставьте пустым для создания или подключения к расшифрованной базе данных.</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="32"/>
+ <source>Encryption password</source>
+ <translation>Пароль для шифрования</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="37"/>
+ <source>Cipher configuration (optional)</source>
+ <translation>Настройки шифрования (необязательно)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="38"/>
+ <source>PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</source>
+ <translation>Конструкции PRAGMA для изменения настроек SQLCipher, таких как количество итераций KDF (функции формирования ключа), режим совместимости и т. д.
+Они будут выполняться при каждом открытии базы данных.
+Для дополнительной информации см. документацию к SQLCipher.</translation>
+ </message>
+ </context>
+</TS>
diff --git a/Plugins/DbSqliteCipher/translations/DbSqliteCipher_sk_SK.ts b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_sk_SK.ts
new file mode 100644
index 0000000..544a00a
--- /dev/null
+++ b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_sk_SK.ts
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="sk" sourcelanguage="en">
+ <context>
+ <name>DbSqliteCipher</name>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="30"/>
+ <source>Password (key)</source>
+ <translation type="unfinished">Password (key)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="31"/>
+ <source>Leave empty to create or connect to decrypted database.</source>
+ <translation type="unfinished">Leave empty to create or connect to decrypted database.</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="32"/>
+ <source>Encryption password</source>
+ <translation type="unfinished">Encryption password</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="37"/>
+ <source>Cipher configuration (optional)</source>
+ <translation type="unfinished">Cipher configuration (optional)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="38"/>
+ <source>PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</source>
+ <translation type="unfinished">PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</translation>
+ </message>
+ </context>
+</TS>
diff --git a/Plugins/DbSqliteCipher/translations/DbSqliteCipher_sr_SP.ts b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_sr_SP.ts
new file mode 100644
index 0000000..86e02f0
--- /dev/null
+++ b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_sr_SP.ts
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="sr" sourcelanguage="en">
+ <context>
+ <name>DbSqliteCipher</name>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="30"/>
+ <source>Password (key)</source>
+ <translation type="unfinished">Password (key)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="31"/>
+ <source>Leave empty to create or connect to decrypted database.</source>
+ <translation type="unfinished">Leave empty to create or connect to decrypted database.</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="32"/>
+ <source>Encryption password</source>
+ <translation type="unfinished">Encryption password</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="37"/>
+ <source>Cipher configuration (optional)</source>
+ <translation type="unfinished">Cipher configuration (optional)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="38"/>
+ <source>PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</source>
+ <translation type="unfinished">PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</translation>
+ </message>
+ </context>
+</TS>
diff --git a/Plugins/DbSqliteCipher/translations/DbSqliteCipher_sv_SE.ts b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_sv_SE.ts
new file mode 100644
index 0000000..c69c8e6
--- /dev/null
+++ b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_sv_SE.ts
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="sv-SE" sourcelanguage="en">
+ <context>
+ <name>DbSqliteCipher</name>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="30"/>
+ <source>Password (key)</source>
+ <translation type="unfinished">Password (key)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="31"/>
+ <source>Leave empty to create or connect to decrypted database.</source>
+ <translation type="unfinished">Leave empty to create or connect to decrypted database.</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="32"/>
+ <source>Encryption password</source>
+ <translation type="unfinished">Encryption password</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="37"/>
+ <source>Cipher configuration (optional)</source>
+ <translation type="unfinished">Cipher configuration (optional)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="38"/>
+ <source>PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</source>
+ <translation type="unfinished">PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</translation>
+ </message>
+ </context>
+</TS>
diff --git a/Plugins/DbSqliteCipher/translations/DbSqliteCipher_tr_TR.ts b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_tr_TR.ts
new file mode 100644
index 0000000..00fece1
--- /dev/null
+++ b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_tr_TR.ts
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="tr" sourcelanguage="en">
+ <context>
+ <name>DbSqliteCipher</name>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="30"/>
+ <source>Password (key)</source>
+ <translation type="unfinished">Password (key)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="31"/>
+ <source>Leave empty to create or connect to decrypted database.</source>
+ <translation type="unfinished">Leave empty to create or connect to decrypted database.</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="32"/>
+ <source>Encryption password</source>
+ <translation type="unfinished">Encryption password</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="37"/>
+ <source>Cipher configuration (optional)</source>
+ <translation type="unfinished">Cipher configuration (optional)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="38"/>
+ <source>PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</source>
+ <translation type="unfinished">PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</translation>
+ </message>
+ </context>
+</TS>
diff --git a/Plugins/DbSqliteCipher/translations/DbSqliteCipher_uk_UA.ts b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_uk_UA.ts
new file mode 100644
index 0000000..39ca873
--- /dev/null
+++ b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_uk_UA.ts
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="uk" sourcelanguage="en">
+ <context>
+ <name>DbSqliteCipher</name>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="30"/>
+ <source>Password (key)</source>
+ <translation type="unfinished">Password (key)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="31"/>
+ <source>Leave empty to create or connect to decrypted database.</source>
+ <translation type="unfinished">Leave empty to create or connect to decrypted database.</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="32"/>
+ <source>Encryption password</source>
+ <translation type="unfinished">Encryption password</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="37"/>
+ <source>Cipher configuration (optional)</source>
+ <translation type="unfinished">Cipher configuration (optional)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="38"/>
+ <source>PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</source>
+ <translation type="unfinished">PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</translation>
+ </message>
+ </context>
+</TS>
diff --git a/Plugins/DbSqliteCipher/translations/DbSqliteCipher_vi_VN.ts b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_vi_VN.ts
new file mode 100644
index 0000000..be657ba
--- /dev/null
+++ b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_vi_VN.ts
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="vi" sourcelanguage="en">
+ <context>
+ <name>DbSqliteCipher</name>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="30"/>
+ <source>Password (key)</source>
+ <translation type="unfinished">Password (key)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="31"/>
+ <source>Leave empty to create or connect to decrypted database.</source>
+ <translation type="unfinished">Leave empty to create or connect to decrypted database.</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="32"/>
+ <source>Encryption password</source>
+ <translation type="unfinished">Encryption password</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="37"/>
+ <source>Cipher configuration (optional)</source>
+ <translation type="unfinished">Cipher configuration (optional)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="38"/>
+ <source>PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</source>
+ <translation type="unfinished">PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</translation>
+ </message>
+ </context>
+</TS>
diff --git a/Plugins/DbSqliteCipher/translations/DbSqliteCipher_zh_CN.ts b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_zh_CN.ts
new file mode 100644
index 0000000..01c5865
--- /dev/null
+++ b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_zh_CN.ts
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="zh-CN" sourcelanguage="en">
+ <context>
+ <name>DbSqliteCipher</name>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="30"/>
+ <source>Password (key)</source>
+ <translation>密码(密钥)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="31"/>
+ <source>Leave empty to create or connect to decrypted database.</source>
+ <translation>留空则创建或连接到已解密的数据库。</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="32"/>
+ <source>Encryption password</source>
+ <translation>加密密码</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="37"/>
+ <source>Cipher configuration (optional)</source>
+ <translation>加密算法配置(可选)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="38"/>
+ <source>PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</source>
+ <translation>用于自定义 SQLCiper 配置的 PRAGMA 语句,如 KDF 迭代、传统模式等。
+将在每次打开数据库时执行。
+细节请参考 SQLCipher 文档。</translation>
+ </message>
+ </context>
+</TS>
diff --git a/Plugins/DbSqliteCipher/translations/DbSqliteCipher_zh_TW.ts b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_zh_TW.ts
new file mode 100644
index 0000000..7945d66
--- /dev/null
+++ b/Plugins/DbSqliteCipher/translations/DbSqliteCipher_zh_TW.ts
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="zh-TW" sourcelanguage="en">
+ <context>
+ <name>DbSqliteCipher</name>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="30"/>
+ <source>Password (key)</source>
+ <translation>密碼 (金鑰)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="31"/>
+ <source>Leave empty to create or connect to decrypted database.</source>
+ <translation>留空則建立或連線到已解密的資料庫。</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="32"/>
+ <source>Encryption password</source>
+ <translation>加密密碼</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="37"/>
+ <source>Cipher configuration (optional)</source>
+ <translation>加密演算法設定檔 (可選)</translation>
+ </message>
+ <message>
+ <location filename="../dbsqlitecipher.cpp" line="38"/>
+ <source>PRAGMA statements to customize SQLCipher configuration, such as KDF iterations, legacy mode, etc.
+They will be executed upon each opening of the database.
+See documentation for SQLCipher for details.</source>
+ <translation>用於自訂 SQLCiper 設定檔的 PRAGMA 語句,如 KDF 迭代、傳統模式等。
+將在每次開啟資料庫時執行。
+細節請參考 SQLCipher 文件。</translation>
+ </message>
+ </context>
+</TS>
diff --git a/Plugins/DbSqliteCipher/update_sqlite_version.tcl b/Plugins/DbSqliteCipher/update_sqlite_version.tcl
index d0d52a7..4b6b04e 100644
--- a/Plugins/DbSqliteCipher/update_sqlite_version.tcl
+++ b/Plugins/DbSqliteCipher/update_sqlite_version.tcl
@@ -5,7 +5,7 @@
# Download page:
# https://github.com/sqlcipher/sqlcipher/releases
-set THE_URL "https://codeload.github.com/sqlcipher/sqlcipher/zip/v4.4.3"
+set THE_URL "https://codeload.github.com/sqlcipher/sqlcipher/zip/v4.5.3"
proc process {} {
if {[catch {